Rockchip · AI & Linux Hub

Cameras & video

Rockchip ISP30 VI Driver V1.1.5: Sensors, VICAP and Camera Debugging

Complete V1.1.5 reference covering RK3588 multi-camera pipelines, CIS and lens drivers, RAW storage, VICAP reset, exposure diagnostics and all five appendices.

· ArmSoM Editorial · Rockchip source documentation · 237 min read

ArmSoM applicability and source scope

This is a Rockchip platform reference, not an ArmSoM hardware test report. The source is Rockchip_Driver_Guide_VI_EN_v1.1.5.pdf, V1.1.5, 230 PDF pages (the last page is blank). No Chinese PDF was supplied. Chinese and Russian translate this English source in full and use its original English figures. All measurements, commands and logs are source examples; no board-specific hardware validation was performed.

The source product table and applicability matrix below differ in scope. The body additionally discusses RK3588/RK3588S and RV1106. ArmSoM Sige7 is officially documented as an RK3588 board with camera usage, but that does not verify compatibility with this source’s legacy SDK, kernel drivers or APIs. Before adaptation, check the exact board and SoC, vendor SDK/BSP and kernel (4.19 or 5.10 as specified), sensor, lane routing, power, clock, DTS, ISP/VICAP topology and IQ/AIQ versions.

This V1.1.5 edition is separate from the existing V1.0.7 article. Both the newer CIS chapter 8 and repeated CIS chapter 10 are retained, including their differences. Source inconsistencies such as differing RK356x limits, node spellings, reset descriptions and exposure formulas are recorded rather than silently corrected. Memory/IOMMU/clock optimization examples require target-specific validation.

Editorial notes · Previous V1.0.7 reference · ArmSoM Sige7 · Official Sige-family setup

Original technical scope (PDF page 2)

Chip Kernel
RV1126/RV1109 Linux 4.19
Chip Software system Support
RV1126 Linux Kernel-4.19 / Kernel-5.10 Y
RV1109 Linux Kernel-4.19 / Kernel-5.10 Y
RK3566 Linux Kernel-5.10 Y
RK3568 Linux Kernel-5.10 Y
RK3562 Linux Kernel-5.10 Y

1. VI difference of the chip

SOC VI IP VI Interface Bayer CIS max resolution Feature
RV1109 ISP20 ( ISP + ISPP): 1 VICAP Full: 1 VICAP Lite: 1 MIPI DPHY: 2 x 4Lanes 2.5Gbps/Lane LVDS: 2 x 4Lanes 1.0Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 3072x2048 Upto 3 frames HDR
RK3566 ISP21 Lite: 1 VICAP Full: 1 MIPI DPHY: 2 x 2Lanes or 1 x 4Lanes 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4096x2304 No HDR
RK3568 ISP21:1 VICAP Full: 1 MIPI DPHY: 2 x 2Lanes or 1 x 4Lanes 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4096x2304 Upto 2 frames HDR
RV1126 ISP20 ( ISP + ISPP): 1 VICAP Full: 1 VICAP Lite: 1 MIPI DPHY: 2 x 4Lanes 2.5Gbps/Lane LVDS: 2 x 4Lanes 1.0Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4416x3312 Upto 3 frames HDR
RK3588 VICAP:1 ISP30:2 FEC:2 MIPI DPHY: 4 x 2Lanes or 2 x 4Lanes 2.5Gbps/Lane MIPI DCPHY: 2 x 4Lanes dphy or 2 x 3Lanes cphy 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4672x3504 single ISP 8192x6144 dual ISP synthesis Upto 3 frames HDR
SOC VI IP VI Interface Bayer CIS max resolution Feature
RK3588S VICAP:1 ISP30:2 FEC:2 MIPI DPHY: 2 x 2Lanes or 1 x 4Lanes 2.5Gbps/Lane MIPI DCPHY: 2 x 4Lanes dphy or 2 x 3Lanes cphy 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4672x3504 single ISP 8192x6144 dual ISP synthesis Upto 3 frames HDR
RV1106 VICAP:1 ISP32:1 MIPI DPHY: 2 x 2Lanes or 1 x 4Lanes 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 3072x1728 Upto 2 frames HDR
RK3562 VICAP:1 ISP32_LITE:1 MIPI DPHY: 2 x 2Lanes or 1 x 4Lanes 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4224x3136 Upto 2 frames HDR

2. Camera software driver catalog description

Linux Kernel-4.19

|-- arch/arm/boot/dts DTS configuration file

|-- drivers/phy/rockchip

|-- phy-rockchip-mipi-rx.c mipi dphy driver

|-- phy-rockchip-csi2-dphy-common.h

|-- phy-rockchip-csi2-dphy-hw.c

|-- phy-rockchip-csi2-dphy.c

|-- drivers/media

|-- platform/rockchip/cif

|-- platform/rockchip/isp

|-- dev Including probe, asynchronous registration, clock, pipeline, iommu and media/v4l2 framework

|-- capture Including mp/sp/rawwr configuration and vb2, frame interrupt processing

|-- dmarx Including rawrd configuration and vb2, frame interrupt processing

|-- isp_params 3A related parameter settings

|-- isp_stats 3A related statistics

|-- isp_mipi_luma mipi data brightness statistics

|-- regs Register-related read and write operations

|-- rkisp isp subdev and entity registration

|-- csi csi subdev and mipi configuration

|-- bridge bridge subdev, isp and ispp interactive bridge

|-- platform/rockchip/ispp

|-- dev Including probe, asynchronous registration, clock, pipeline, iommu and media/v4l2 framework

|-- stream Including 4 video output configuration and vb2, frame interrupt processing

|-- rkispp ispp subdev and entity registration

|-- params TNR/NR/SHP/FEC/ORB parameter setting

|-- stats ORB statistics

|-- i2c

|-- os04a10.c CIS (cmos image sensor) driver

For the RV1126/RV1109 and RK356X platforms, VICAP and ISP are two independent image processing IPs. If the images collected by VICAP are processed by ISP, the v4l2 sub device of the VICAP corresponding interface needs to be generated at the driver level to link to the node corresponding to the ISP. , To provide parameters for the ISP driver to use. Please refer to RKISP driver for ISP driver description and RKVICAP driver for VICAP driver description. The overall block diagram of the specific VICAP interfaces and the ISP link is as follows:

ISP and VICAP connection topology — original English figure, PDF page 10

ISP and VICAP connection topology — original English figure, PDF page 10

4. RKISP driver

4.1 Brief description of the framework

The RKISP driver is mainly based on the v4l2/media framework to implement hardware configuration, interrupt processing, control buffer rotation, and control the power on and off of subdevices (such as MIPI DPHY and sensor).

The following block diagram describes the topology of the RKISP driver:

RKISP driver topology — original English figure, PDF page 11

RKISP driver topology — original English figure, PDF page 11

Name Type Description
rkisp_mainpath v4l2_vdevcapture Format: YUV, RAW Bayer; Support: Crop,scale(no for raw)
rkisp_selfpath v4l2_vdevcapture Format: YUV, RGB; Support: Crop,scale(no for raw)
rkisp-isp-subdev v4l2_subdev Internal isp blocks; Support: source/sink pad crop. The format on sink pad equal to sensor input format, the size equal to sensor input size. The format on source pad should be equal to vdev output format if output format is raw bayer, otherwise it should be YUYV2X8. The size should be equal/less than sink pad size.
rkisp-mipi-luma v42_vdevcapture Provice raw image luma
rkisp-statistics v4l2_vdevcapture Provide Image color Statistics information.
rkisp-input-params v4l2_vdevoutput Accept params for AWB, BLC…… Image enhancement blocks.
rkisp_rawrd0_m v4l2_vdevoutput Raw image read from DDR to ISP, usually using for the HDR middle frame
rkisp_rawrd1_l v4l2_vdevoutput Raw image read from DDR to ISP, usually using for the HDR long frame
rkisp_rawrd2_s v4l2_vdevoutput Raw image read from DDR to ISP, usually using for the HDR short frame
rkisp-csi-subdev v4l2_subdev MIPI CSI configure
rkisp_rawwr0 v4l2_vdevcapture Raw image write to DDR from sensor, usually using for the HDR middle frame
rkisp_rawwr1 v4l2_vdevcapture Raw image write to DDRfrom sensor, usually using for the HDR long frame
rkisp_rawwr2 v4l2_vdevcapture Raw image write to DDR from sensor, usually using for the HDR short frame
rkisp_rawwr3 v4l2_vdevcapture Raw image write to DDR from sensor
rockchip-mipi- dphy-rx v4l2_subdev MIPI-DPHY Configure.
rkisp-bridge-ispp v4l2_subdev ISP output yuv image to ISPP
rkispp_input_image v4l2_vdevoutput Yuv image read from DDR to ISPP
rkisp-isp-subdev v4l2_subdev The format and size on sink pad equal to ISP output. The support max size is 4416x3312, min size is 66x258
rkispp_m_bypass v4l2_vdev capture Full resolution and yuv format
Name Type Description
rkispp_scale0 v4l2_vdev capture Full or scale resolution and yuv format Scale range:[1 8] ratio 3264 max width for yuv422 2080 max width for yuv420 only for rv1126
rkispp_scale1 v4l2_vdev capture Full or scale resolution and yuv format Scale range:[2 8] ratio 1280 max width only for rv1126
rkispp_scale2 v4l2_vdev capture Full or scale resolution and yuv format Scale range:[2 8] ratio 1280 max width only for rv1126

4.2 ISP HDR mode description

RKISP2 supports receiving MIPI sensor to output HDR 3 frames or 2 frames mode, the hardware collects data to DDR through 3 or 2 dmatx, and then reads the ISP through 3 or 2 dmarx, and the ISP does 3 or 2 frames synthesis, drive chain The road is as follows:

Three-frame HDR path — original English figure, PDF page 13

Three-frame HDR path — original English figure, PDF page 13

Two-frame HDR path — original English figure, PDF page 13

Two-frame HDR path — original English figure, PDF page 13

The CSI subdev obtains the output information of the sensor driver in multiple pad formats through get_fmt, which corresponds to the source pad of the CSI.

Please refer to the specific configuration of MIPI sensor driver Driver migration steps

Name Name Description
rkisp-isp- subdev Sensor pad0 ISP capture Sensor vc0 (default) wide and high format output, commonly used linear mode
rkisp_rawwr0 Sensor pad1 Rawwr0 capture sensor vcX wide and high format output
rkisp_rawwr1 Sensor pad2 Rawwr1 capture sensor vcX wide and high format output
rkisp_rawwr2 Sensor pad3 Rawwr2 capture sensor vcX wide and high format output
rkisp_rawwr3 Sensor pad4 Rawwr3 capture sensor vcX wide and high format output

5. RKVICAP driver

5.1 Frame description

The RKVICAP driver is mainly based on the v4l2/media framework to implement hardware configuration, interrupt processing, control buffer rotation, and control the power on and off of subdevices (such as mipi dphy and sensor).

For RV1126/RV1109, VICAP has two IP cores, one of which is called VICAP FULL and the other is called VICAP LITE. VICAP FULL has three interfaces: dvp/mipi/lvds, dvp can work with mipi or lvds interface at the same time, but mipi and lvds cannot work at the same time, VICAP LITE only has lvds interface, which can work with VICAP FULL interface at the same time; VICAP FULL dvp The interface corresponds to a rkvicap_dvp node, the VICAP FULL mipi/lvds interface corresponds to a rkvicap_mipi_lvds node, and the VICAP LITE corresponds to a rkvicap_lite_mipi_lvds node. Each node can be collected independently.

For the RK356X chip, VICAP has only a single core and has two interfaces, dvp and mipi. The dvp interface corresponds to a rkvicap_dvp node, and the mipi interface corresponds to a rkvicap_mipi_lvds node (the same name as the VICAP FULL of RV1126/RV1109), and each node can be collected independently.

In order to synchronize the data collected by VICAP to the isp driver, it is necessary to link the logical sditf node generated by the VICAP driver to the virtual node device generated by the isp. The DVP interface corresponds to the rkvicap_dvp_sditf node, the mipi/lvds interface of VICAP FULL corresponds to the rkvicap_mipi_lvds_sditf node, and the VICAP LITE corresponds to rkvicap_lite_sditf.

Please refer to the specific dts link method of each interface CIS Device Registration (DTS)

The following figure describes the topology of the device driven by RKVICAP:

VICAP interface topology — original English figure, PDF page 15

VICAP interface topology — original English figure, PDF page 15

6. RK3588 VI structure

7. Hardware Block

RK3588 VI hardware blocks — original English figure, PDF page 16

RK3588 VI hardware blocks — original English figure, PDF page 16

7.1 Multi-sensor support

A single hardware ISP supports up to four multiplexes, and the supported resolutions for ISP multiplexing are as follows:

2-way multiplexing: The maximum resolution is 3840x2160, and DTS corresponds to the configuration of 2-way rkisp_vir devices.

3-way or 4-way multiplexing: The maximum resolution is 2560x1536, and DTS corresponds to the configuration of 3 or 4-way rkisp_vir devices.

The hardware supports the acquisition of up to 7 sensors: 6MIPI + 1DVP, and the multi-sensor software path is as follows:

RK3588 multi-sensor paths — original English figure, PDF page 16

RK3588 multi-sensor paths — original English figure, PDF page 16

Block diagram description:

1. The RK3588 supports two DCPHYs with node names of csi2_dcphy0/csi2_dcphy1. Each dcphy hardware supports RX/TX at the same time, and RX is used for camera inputs. Support DPHY/CPHY protocol multiplexing; It should be noted that TX/RX of the same dcphy can only use DPHY at the same time or CPHY at the same time. Other DCPHY parameters can be found in the RK3588 data sheet. 2. RK3588 supports 2 DPY hardware, here we call it dphy0_hw/dphy1_hw, both DPHY hardware can work in Full Mode and Split Mode modes. 1. dphy0_hw 1. Full Mode: The node name is csi2_dphy0, and up to 4 lanes are supported. 2. Split Mode: Split into 2 PHYs, which are csi2_dphy1 (using 0/1 lane) and csi2_dphy2 (using 2/3 LANE), each PHY supports up to 2 lanes. 3. When dphy0_hw uses full mode, the link needs to be configured according to the csi2_dphy1 link, but the node name csi2_dphy1 needs to be modified to csi2_dphy0, and the software is distinguished by the sequence number of PHY to distinguish the mode used by PHY. 2. dphy1_hw 1. Full Mode: The node name uses csi2_dphy3, and supports up to 4 lanes. 2. Split Mode: Split into 2 PHYs, which are csi2_dphy4 (using 0/1 lane) and csi2_dphy5 (using 2/3 LANE), each PHY supports up to 2 lanes. 3. When dphy1_hw uses full mode, the link needs to be configured according to the csi2_dphy4 link, but the node name csi2_dphy4 need to be modified to csi2_dphy3, and the software is to distinguish the mode used by the PHY sequence number. 3. To use the above MIPI PHY node, you need to configure the corresponding physical node. (csi2_dcphy0_hw/csi2_dcphy1_hw/csi2_dphy0_hw/csi2_dphy1_hw) 4. Each MIPI PHY requires a CSI2 module to parse the MIPI protocol, and the node names are mipi0_csi2~mipi5_csi2. 5. All camera data in RK3588 needs to be linked to the ISP through ViCap. RK3588 only supports one VICAP hardware, this VICAP supports simultaneous input of 6 MIPI PHYs, and one DVP data, so we divide VICAP into 7 nodes such as rkcif_mipi_lvds~rkcif_mipi_lvds5, rkcif_dvp, etc., and the binding relationship of each node needs to be configured in strict accordance with the node serial number of the block diagram. 6. The link relationship between each VICAP node and the ISP indicates the link relationship by corresponding to the virtual XXX_sditf. 7. The RK3588 supports 2 ISP hardware, each ISP device can virtualize multiple virtual nodes, and the software reads each image data from the DDR in turn into the ISP for processing. For multi-camera scenarios, it is recommended to distribute the data stream evenly between the two ISPs. 8. Pass-through and readback modes: 1. Pass-through: means that the data is collected by VICAP, sent directly to the ISP for processing, and is not stored in DDR. It should be noted that when HDR pass-through, only short frames are true pass-through, long frames need to exist DDR, and ISP reads from DDR. 2. Read back: It means that the data is collected to the DDR through VICAP, and after the application obtains the data, it pushes the buffer address to the ISP, and the ISP obtains the image data from the DDR. 3. When configuring DTS again, if only one virtual node is configured, passthrough mode is used by default for an ISP hardware, and readback mode is used by default if multiple virtual nodes are configured.

7.2 Dual ISP synthesis supports 8K resolution

VICAP collects sensor 8K data, then sends the left and right images to two ISPs for processing, and then outputs them to DDR, the process is as follows:

Dual-ISP 8K synthesis — original English figure, PDF page 18

Dual-ISP 8K synthesis — original English figure, PDF page 18

When the resolution is greater than 16M (4672x3504), two ISPs need to be used at the same time to process one image, and only single camera is supported.

1. From the rk3588s.dtsi file, you can find the three definitions of rkisp0, rkisp1, and rkisp_unite, when the resolution to be processed is greater than 16M, you need to close the rkisp0 and rkisp1 nodes, and enable the rkisp_unite, while modifying the corresponding iommu node.

2. Using rkisp_unite nodes can also virtualize multiple nodes, at this time, regardless of the resolution, the same image is cropped into two pictures, left and right, sent 2 ISPs for processing, and then synthesized into an output.

3. DTS Configuration Reference 待链接

7.3 8 mesh MIPI sensor support

RK3588 hardware supports up to 6 mipi sensors, which can be expanded by RK1608 splicing, RK1608 supports 4 MIPI inputs (1, 2, 4lane), two MIPI outputs (1, 2, 4lane), through RK1608 splicing 3 + original 5 MIPI can achieve 8 MIPI sensor inputs, the hardware connection is as follows:

RK1608 eight-MIPI-sensor connection — original English figure, PDF page 18

RK1608 eight-MIPI-sensor connection — original English figure, PDF page 18

Software, you need to enable the RK1608 driver in the kernel’s defconfig:

  CONFIG_VIDEO_ROCKCHIP_PREISP=y
  CONFIG_VIDEO_PREISP_DUMMY_SENSOR=y

On the dts link, RK1608 abstracts the RK1608 dphy node and enters it as a virtual preisp_dmy sensor. RK1608 dphy, like ordinary sensors, is connected to RK3588 dcphy to form an RK1608->dcphy->csi->cif lvds link. The sensor physically hung in the RK1608 is directly hung in the rkcif_mipi_lvdsx_sditf, rkcif_mipi_lvdsx_sditf_vir1, rkcif_mipi_lvdsx_sditf_vir2, and rkcif_mipi_lvdsx_sditf_vir3 port0 in the dts as the input of the SDITF device.

The output of SDITF is consistent with the original path, and is the corresponding ISP node. The DTS link is shown as follows:

RK1608 DTS link topology — original English figure, PDF page 19

RK1608 DTS link topology — original English figure, PDF page 19

The dts configuration of RK1608 is mainly on the rk1608-dpy device node, which mainly includes input and output channels and resolution, as follows:

  #define LINK_FREQ               700000000
      mipidphy0: mipidphy0 {
      compatible =  "rockchip,rk1608-dphy";
          status = "okay";
          //rockchip,grf = <&grf>;
          id = <0>;  //RK1608 internal ID (0-2, spliced sequentially by ID)
          cam_nums = <1>;
          in_mipi = <1>;         //Input MIPI channel of the first sensor (0-3)
          out_mipi = <0>;        //Output MIPI channel (0-1)
          link-freqs = /bits/ 64 <LINK_FREQ>; //MIPI rate
          sensor_i2c_bus = <5>;     //The 8-mesh pattern is invalid
          sensor_i2c_addr = <0x1a>; //The 8-mesh pattern is invalid
          sensor-name = "IMX464";
          rockchip,camera-module-index = <9>; //Same as ordinary sensor
          rockchip,camera-module-facing = "back";
          rockchip,camera-module-name = "TongJu";
          rockchip,camera-module-lens-name = "CHT842-MD";
          /* virtual-sensor mode */
          virtual-sub-sensor-config-0 {  //Configuration information for the second
  sensor
              id = <1>;  //RK1608 internal ID (0-2, spliced by ID)
              in_mipi = <2>;
              out_mipi = <1>;
          };
          virtual-sub-sensor-config-1 { //Configuration information for the third
  sensor
              id = <2>;  //RK1608 internal ID (0-2, spliced by ID)
              in_mipi = <3>;
              out_mipi = <1>;
          };
          /* multi-sensor mode end */
          format-config-0 {
              data_type = <0x2b>;
              mipi_lane = <2>;     //The number of lanes connected to the sensor
              mipi_lane_out = <4>; //The number of lanes output by RK1608
              field = <1>;      //The following is the same as the normal sensor
  configuration
              colorspace = <8>;
              code = <MEDIA_BUS_FMT_SRGGB10_1X10>;
              width = <2712>;  //Sensor output resolution
              height= <1538>;
              hactive = <2712>; //RK1608 output resolution, the same width, height
  is n*sensor
              vactive = <4614>;
              htotal = <3616>; //After increasing the width and height of blank,
  30% of the blank is generally required
              vtotal = <4710>;
              inch0-info = <2712 1538 0x2b 0x2b 1>; //Sensor output resolution
              outch0-info = <2712 4614 0x2b 0x2b 1>; //RK1608 output resolution
              hcrop = <2560>; //Single resolution after cropping
              vcrop = <1520>;
          };
          ...

The DTS configuration reference of the sensor is as follows:

  &rkcif_mipi_lvds_sditf {
      #address-cells = <1>;
      #size-cells = <0>;
      status = "okay";
      rockchip,combine-index = <0>; //Order in RK1608 stitching diagram
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_lvds_sditf_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&imx464_out7>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_lvds_sditf: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&isp0_vir0>;
              };
          };
      };
  };

8. CIS (CMOS image sensor) driver

8.1 CIS Device Registration (DTS)

8.1.1 MIPI interface

For the RV1126 and RV1106 platforms, there are two separate and complete standard physical MIPI CSI2 DPYs, corresponding to the csi_dphy0 and csi_dphy1 on the DTS (see RV1126.DTSI), with the following characteristics:

Data lanes are up to 4 lanes;

Maximum speed 2.5Gbps/lane;

For the RK356X platform, there is only one standard physical mipi csi2 dphy, which can operate in two modes: full mode and split mode, split into three logical dphys csi2_dphy0/csi2_dphy1/csi2_dphy2 (see rk3568.dtsi), with the following characteristics:

Full mode

Only use csi2_dphy0, csi2_dphy0 and csi2_dphy1/csi2_dphy2 mutually exclusive, not at the same time;

Data lanes up to 4 lanes;

Maximum speed 2.5Gbps/lane;

Split mode

Use only csi2_dphy1 and csi2_dphy2, mutually exclusive with csi2_dphy0, not at the same time;

csi2_dphy1 and csi2_dphy2 can be used at the same time;

The maximum data lanes of csi2_dphy1 and csi2_dphy2 are 2 lanes;

csi2_dphy1 lane0/lane1 corresponding to physical DPY;

csi2_dphy2 Lane2/LANE3 corresponding to physical DPY;

Maximum rate 2.5Gbps/lane

For specific DTS use cases, see the following examples.

8.1.1.1.1 RV1126/RV1106

The following is an example of RV1126 ISP and OS04A10.

Link relationship: sensor->csi_dphy->isp->ispp

arch/arm/boot/dts/rv1126-evb-v10.dtsi

Configuration Essentials

Data-lanes must indicate the specific number of lanes used, otherwise they cannot be recognized as mipi types;

  cam_ircut0: cam_ircut {
      status = "okay";
      compatible = "rockchip,ircut";
      ircut-open-gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_HIGH>;
      ircut-close-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
      rockchip,camera-module-index = <1>;
      rockchip,camera-module-facing = "front";
  };
  os04a10: os04a10@36 {
      compatible = "ovti,os04a10";// It needs to match the matching string in the
  driver
      reg = <0x36>;// sensor I2C device address, 7 bits
      clocks = <&cru CLK_MIPICSI_OUT>;// Sensor clickin configuration
      clock-names = "xvclk";
      power-domains = <&power RV1126_PD_VI>;
      pinctrl-names = "rockchip,camera_default";
      pinctrl-0 = <&mipi_csi_clk0>;// PINCTL settings
      //power supply
      avdd-supply = <&vcc_avdd>;
      dovdd-supply = <&vcc_dovdd>;
      dvdd-supply = <&vcc_dvdd>;
      // Power pin assignment and active level
      pwdn-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
      // Module number, which should not be repeated
      rockchip,camera-module-index = <1>;
      // Module orientation, with "back" and "front"
      rockchip,camera-module-facing = "front";
      // Module name
      rockchip,camera-module-name = "CMK-OT1607-FV1";
      // Lens name
      rockchip,camera-module-lens-name = "M12-4IR-4MP-F16";
      //IR CUT equipment
      ir-cut = <&cam_ircut0>;
      port {
          ucam_out0: endpoint {
              // The port name on the mipi dphy side
              remote-endpoint = <&mipi_in_ucam0>;
              // MIPI lanes number, 1 lane is <1>,
              4lane is <1 2 3 4 >
              data-lanes = <1 2 3 4>;
          };
      };
   };
  &csi_dphy0 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name on the sensor side
                  remote-endpoint = <&ucam_out0>;
                  // MIPI lanes number, 1 lane is <1>, 4lane is
  <1 2 3 4 >,data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // The port name on the ISP side
                  remote-endpoint = <&isp_in>;
              };
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  // The port name on the mipi dphy side
                  remote-endpoint = <&csidphy0_out>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp0_out: endpoint@1 {
                  reg = <1>;
                  // ISP port name, ISP output to ISP
                  remote-endpoint = <&ispp0_in>;
              };
          };
      };
  };
  &rkispp {
      status = "okay";
  };
  &rkispp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          Ispp0_in: endpoint@0 {
              reg = <0>;
              // ISP port name, ISPP input
              remote-endpoint = <&isp0_out>;
          };
      };
  };
8.1.1.1.2 RK356X

The following is an example of RK3566 ISP and GC8034 4LANE:

Link relationship: sensor->csi2_dphy0->isp Configuration Essentials

Data-lanes need to be configured

Requires csi2_dphy_hw node to be enabled

   /* full mode: lane0-3 */
      gc8034: gc8034@37 {
          // It needs to match the matching string in the driver
          compatible = "galaxycore,gc8034";
          status = "okay";
          // sensor I2C device address, 7 bits
          reg = <0x37>;
          // Sensor mclk source configuration
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          //The sensor dependent power domain is enabled
          power-domains = <&power RK3568_PD_VI>;
          //Sensor McLk pinctl settings
          pinctrl-names = "default";
          pinctrl-0 = <&cif_clk>;
          // Reset pin assignment and active level
          reset-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
          // Powerdown pin assignment and active level
          pwdn-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_LOW>;
          // Module number, which should not be repeated
          rockchip,camera-module-index = <0>;
          // Module orientation, with "back" and "front"
          rockchip,camera-module-facing = "back";
          // Module name
          rockchip,camera-module-name = "RK-CMK-8M-2-v1";
          // Lens name
          rockchip,camera-module-lens-name = "CK8401";
          port {
              gc8034_out: endpoint {
                  // The port name of the CSI2 dphy end
                  remote-endpoint = <&dphy0_in>;
                  // CSI2 dphy lane number, 1lane is <1>,
                  4lane is <1 2 3 4>, data-lanes = <1 2 3 4>;
              };
          };
      };
      &csi2_dphy_hw {
         status = "okay";
      };
      &csi2_dphy0 {
          //csi2_dphy0 is not used at the same time as
          csi2_dphy1/csi2_dphy2, mutually exclusive
          status = "okay";
          /*
           * dphy0 only used for full mode,
           * full mode and split mode are mutually exclusive
           */
          ports {
              #address-cells = <1>;
              #size-cells = <0>;
              port@0 {
                  reg = <0>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  dphy0_in: endpoint@1 {
                      reg = <1>;
                      // The port name on the sensor side
                      remote-endpoint = <&gc8034_out>;
                      // CSI2 dphy lanes, 1 lane is <1 >, 4 lanes is <1 2 3 4 >,
  which needs to be consistent with the sensor side
                          data-lanes = <1 2 3 4>;
                  };
              };
              port@1 {
                  reg = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  dphy0_out: endpoint@1 {
                      reg = <1>;
                      // The port name on the ISP side
                      remote-endpoint = <&isp0_in>;
                  };
              };
          };
      };
  &rkisp {
      status = "okay";
  };
  &rkisp_mmu {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp0_in: endpoint@0 {
              reg = <0>;
              // The port name of the CSI2 dphy side
              remote-endpoint = <&dphy0_out>;
          };
      };
  };
8.1.1.2.1 RV1126/RV1109

Take MIPI OS04A10 4 Lanes Link VICAP as an example:

Link relationship: sensor->csi dphy->mipi csi host->vicap Configuration Points:

Data-lanes must indicate the specific number of lanes used, otherwise they cannot be recognized as MIPI types;

dphy needs to be linked to the CSI Host node.

  os04a10: os04a10@36 {
          // It needs to match the matching string in the driver
          compatible = "ovti,os04a10";
          // sensor I2C device address, 7 bits
          reg = <0x36>;
          // Sensor mclk source configuration
          clocks = <&cru CLK_MIPICSI_OUT>;
          clock-names = "xvclk";
          //The sensor dependent power domain is enabled
          power-domains = <&power RV1126_PD_VI>;
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          //Sensor McLk pinctl settings
          pinctrl-names = "rockchip,camera_default";
          pinctrl-0 = <&mipicsi_clk0>;
          // Powerdown pin assignment and active level
          pwdn-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
          // Module number, which should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, with "back" and "front"
          rockchip,camera-module-facing = "front";
          // Module name
          rockchip,camera-module-name = "CMK-OT1607-FV1";
          // Lens name
          rockchip,camera-module-lens-name = "M12-40IRC-4MP-F16";
          // Ircut name
          ir-cut = <&cam_ircut0>;
          port {
              ucam_out0: endpoint {
                  // The port name of the CSI2 dphy end
                  remote-endpoint = <&mipi_in_ucam0>;
                  // CSI2 dphy lanes number, 1lane is <1>, 4lane is <1 2 3 4 >
                  data-lanes = <1 2 3 4>;
              };
          };
      };
  &csi_dphy0 {
      //csi2_dphy0 is not used at the same time as csi2_dphy1/csi2_dphy2, mutually exclusive
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name on the sensor side
                  remote-endpoint = <&ucam_out0>;
                  // CSI2 dphy lanes, 1 lane is <1 >, 4 lanes is <1 2 3 4 >, which
  needs to be consistent with the sensor side
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // The port name of the CSI2 host
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  // The port name of the CSI2 host
                  remote-endpoint = <&csidphy0_out>;
                  // CSI2 host lanes, 1 lane is <1>,
                  4lane is <1 2 3 4 >, which needs to be
                  consistent with the sensor side
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  // The port name on the vicap side
                  remote-endpoint = <&cif_mipi_in>;
                  // CSI2 host lanes, 1 lane is <1>,
                  4lane is <1 2 3 4 >, which needs to be
                  consistent with the sensor side
                  data-lanes = <1 2 3 4>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          /* MIPI CSI-2 endpoint */
          cif_mipi_in: endpoint {
              // The port name of the CSI2 host
              remote-endpoint = <&mipi_csi2_output>;
              // The number of lanes on the vicap side,
              1 lane is <1 >, 4lane is < 1 2 3 4 >,
              which needs to be consistent with the sensor side
              data-lanes = <1 2 3 4>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          /* sditf endpoint */
          mipi_lvds_sditf: endpoint {
              //ISP virtual device port name
              remote-endpoint = <&isp_in>;
              //The number of lanes of MIPI CSI2 dphy,
              consistent with the sensor
              data-lanes = <1 2 3 4>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //The endpoint name of the Vicap SDITF
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };
8.1.1.2.2 RK356X

Take the example of lane2/lane3 of GC5025 2lane link rk3566 EVB2 mipi CSI2 dphy:

Link relationship: sensor->csi2 dphy->mipi CSI host->vicap Configuration Essentials

Data-lanes must indicate the specific number of lanes used, otherwise they cannot be recognized as MIPI types;

dphy needs to be linked to the CSI Host node;

The CSI2 dphy HW node needs to be enabled.

  /* split mode: lane:2/3 */
  gc5025: gc5025@37 {
          status = "okay";
          // It needs to match the matching string in the driver
          compatible = "galaxycore,gc5025";
          // sensor I2C device address, 7 bits
          reg = <0x37>;
          // Sensor mclk source configuration
          clocks = <&pmucru CLK_WIFI>;
          clock-names = "xvclk";
          //Sensor McLk pinctl settings
          pinctrl-names = "default";
          pinctrl-0 = <&refclk_pins>;
          // Reset pin assignment and active level
          reset-gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
          // Powerdown pin assignment and active level
          pwdn-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
          // The sensor dependent power domain is enabled
          power-domains = <&power RK3568_PD_VI>;
          /*power-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;*/
          // Module number, which should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, with "back" and "front"
          rockchip,camera-module-facing = "front";
          // Module name
          rockchip,camera-module-name = "TongJu";
          // Lens name
          rockchip,camera-module-lens-name = "CHT842-MD";
          port {
              gc5025_out: endpoint {
                  // The port name of the CSI2 dphy end
                  remote-endpoint = <&dphy2_in>;
                  // CSI2 dphy lanes number, 2lanes are <1 2>, 4lanes are <1 2 3 4
  >
                  data-lanes = <1 2>;
              };
          };
  };
   &csi2_dphy_hw {
           status = "okay";
   };
  &csi2_dphy2 {
      //csi2_dphy2 is not used at the same time as csi2_dphy0, mutually exclusive;
  Can be used in parallel with csi2_dphy1
      status = "okay";
      /*
       * dphy2 only used for split mode,
       * can be used  concurrently  with dphy1
       * full mode and split mode are mutually exclusive
       */
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  // The port name on the sensor side
                  remote-endpoint = <&gc5025_out>;
                  // CSI2 dphy lanes, 2lane is <1 2>, 4lane is <1 2 3 4 >, which
  needs to be consistent with the sensor side
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  // The port name of the CSI2 host
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  // The port name on the CSI2 dphy side
                  remote-endpoint = <&dphy2_out>;
                  // CSI2 host lanes, 2 lanes are <1 2>, 4lanes are <1 2 3 4 >,
  which need to be consistent with the sensor side
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  // The port name on the vicap side
                  remote-endpoint = <&cif_mipi_in>;
                  // CSI2 host lanes, 1 lane is <1>, 4lane is <1 2 3 4 >, which
  needs to be consistent with the sensor side
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              // The port name of the CSI2 host
              remote-endpoint = <&mipi_csi2_output>;
              // The number of lanes on the vicap side, 2lane is <1 2>, 4lane is <1
  2 3 4 >, which needs to be consistent with the sensor side
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          /* MIPI CSI-2 endpoint */
          mipi_lvds_sditf: endpoint {
              //ISP virtual device port name
              remote-endpoint = <&isp_in>;
              //The number of lanes of MIPI CSI2 dphy, consistent with the sensor
              data-lanes = <1 2>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //The endpoint name of Vicap Mipi SDITF
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };
8.1.1.2.3 RK3588

Take IMX464 connected to DPY1 as an example

Data-lanes must indicate the specific number of lanes used, otherwise they cannot be recognized as mipi types;

dphy needs to be linked to the CSI Host node, csi2_dphy3 corresponds to the mipi4_csi2 used;

csi2_dphy3 are just logical nodes and need to rely on physical nodes csi2_dphy1_hw.

rkcif_mipi_lvds4 is one of the logical nodes of vicap, and the physical node rkcif and corresponding iommu need to be configured.

rkcif_mipi_lvds4_sditf is a virtual child node, which is a rkcif_mipi_lvds4 virtual node that is used to link ISPs.

The sensor driver generally realizes AVDD/DVDD/DOVDD three power supply operation, if the power supply similar to the RAK809 allocated can be directly configured on the sensor node, if the LDO and other external power supplies, the enabling pin is controlled by GPIO, you can refer to the vcc_mipicsi1 configured as a power node, can be powered up and down by reference counting, suitable for multiple devices using the same power supply. It is recommended that the DVD power supply is supplied separately when multi-camera, AVDD/DOVDD can be shared, and when the DVD is shared, if the power is relatively large, there may be an instantaneous shortage of supply, and the power supply will collapse, affecting the image quality, or even not drawing.

      / {
          vcc_mipicsi1: vcc-mipicsi1-regulator {
              compatible = "regulator-fixed";
              gpio = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
              pinctrl-names = "default";
              pinctrl-0 = <&mipicsi1_pwr>;
              regulator-name = "vcc_mipicsi1";
              enable-active-high;
          };
      };
      &csi2_dphy1_hw {
          status = "okay";
      };
      &csi2_dphy3 {
          status = "okay";
          ports {
              #address-cells = <1>;
              #size-cells = <0>;
              port@0 {
                  reg = <0>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  mipi_in_ucam: endpoint@1 {
                      reg = <1>;
                      remote-endpoint = <&imx464_out>;
                      data-lanes = <1 2 3 4>;
                  };
              };
              port@1 {
                  reg = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  csidphy3_out: endpoint@0 {
                      reg = <0>;
                      remote-endpoint = <&mipi4_csi2_input>;
                  };
              };
          };
      };
      &i2c4 {
          status = "okay";
          pinctrl-0 = <&i2c4m3_xfer>;
          imx464: imx464@36 {
              compatible = "sony,imx464";
              status = "okay";
              reg = <0x36>;
              clocks = <&cru CLK_MIPI_CAMARAOUT_M4>;
              clock-names = "xvclk";
              pinctrl-names = "default";
              pinctrl-0 = <&mipim0_camera4_clk>;
              avdd-supply = <&vcc_mipicsi1>;
              reset-gpios = <&gpio1 RK_PD6 GPIO_ACTIVE_HIGH>;
              pwdn-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
              rockchip,camera-module-index = <0>;
              rockchip,camera-module-facing = "back";
              rockchip,camera-module-name = "CMK-OT1980-PX1";
              rockchip,camera-module-lens-name = "SHG102";
              port {
                  imx464_out: endpoint {
                      remote-endpoint = <&mipi_in_ucam>;
                      data-lanes = <1 2 3 4>;
                  };
              };
          };
      };
      &mipi4_csi2 {
          status = "okay";
          ports {
              #address-cells = <1>;
              #size-cells = <0>;
              port@0 {
                  reg = <0>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  mipi4_csi2_input: endpoint@1 {
                      reg = <1>;
                      remote-endpoint = <&csidphy3_out>;
                  };
              };
              port@1 {
                  reg = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  mipi4_csi2_output: endpoint@0 {
                      reg = <0>;
                      remote-endpoint = <&cif_mipi_in4>;
                  };
              };
          };
      };
      &pinctrl {
          cam {
              mipicsi1_pwr: mipicsi1-pwr {
                  rockchip,pins =
                      /* camera power en */
                      <4 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
              };
          };
      };
      &rkcif {
          status = "okay";
      };
      &rkcif_mipi_lvds4 {
          status = "okay";
          port {
              cif_mipi_in4: endpoint {
                  remote-endpoint = <&mipi4_csi2_output>;
              };
          };
      };
      &rkcif_mipi_lvds4_sditf {
          status = "okay";
          port {
              mipi4_lvds_sditf: endpoint {
                  remote-endpoint = <&isp0_vir0>;
              };
          };
      };
      &rkcif_mmu {
          status = "okay";
      };
      #if 1
      &rkisp0 {
          status = "okay";
          /* the max input w h and fps of mulit sensor */
          //max-input = <2688 1520 30>;多摄sensor分辨率不一样,需要配置
      };
      &isp0_mmu {
          status = "okay";
      };
      #else //sensor分辨率大于16M(4672x3504)需要2个isp合成处理
      /* dual isp case need width 32 align, height 8 align */
      &rkisp_unite_mmu {
          status = "okay";
      };
      &rkisp_unite {
             status = "okay";
      };
      &rkisp0_vir0 {
             status = "okay";
             rockchip,hw = <&rkisp_unite>;
      };
      #endif
      &rkisp0_vir0 {
          status = "okay";
          port {
              #address-cells = <1>;
              #size-cells = <0>;
              isp0_vir0: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&mipi4_lvds_sditf>;
              };
          };
      };
8.1.1.2.4 RV1106

DTS configuration refer to arch/arm/boot/dts/rv1106-evb-cam.dtsi

8.1.1.2.5 ***RK3562

DTS configuration refer to arch/arm64/boot/dts/rockchip/rk3562-evb1-cam.dtsi

8.1.2 LVDS interface

8.1.2.1.1 RV1126/RV1109

Taking IMX327 4lane as an example, the link relationship is as follows:

Link relationship: sensor->csi dphy->vicap Configuration Essentials

dphy does not need to link the CSI Host node, otherwise it will not receive data;

Data-lanes must indicate the specific number of lanes used, otherwise data will not be received;

bus-type must be configured as 3, otherwise it cannot be recognized as an LVDS interface, resulting in link establishment failure;

  imx327: imx327@1a {
          // It needs to match the matching string in the driver
          compatible = "sony,imx327";
          // sensor I2C device address, 7 bits
          reg = <0x1a>;
          // Sensor mclk source configuration
          clocks = <&cru CLK_MIPICSI_OUT>;
          clock-names = "xvclk";
          //The sensor dependent power domain is enabled
          power-domains = <&power RV1126_PD_VI>;
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          //Sensor McLk pinctl settings
          pinctrl-names = "default";
          pinctrl-0 = <&mipicsi_clk0>;
          // Powerdown pin assignment and active level
          pwdn-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
          // Reset pin assignment and active level
          reset-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
          // Module number, which should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, with "back" and "front"
          rockchip,camera-module-facing = "front";
          // Module name
          rockchip,camera-module-name = "CMK-OT1607-FV1";
          // Lens name
          rockchip,camera-module-lens-name = "M12-4IR-4MP-F16";
          // Ircut name
          ir-cut = <&cam_ircut0>;
          port {
              ucam_out0: endpoint {
                  // The port name of the CSI2 dphy end
                  remote-endpoint = <&mipi_in_ucam0>;
                  //CSI2 dphy lvds number of lanes, 1 lane is <1>, 4lane is <4 >,
  must be specified
                  data-lanes = <4>;
                  //The type of LVDS interface, which must be specified
                  bus-type = <3>;
              };
          };
  };
  &csi_dphy0 {
      //csi2_dphy0 is not used at the same time as csi2_dphy1/csi2_dphy2, mutually exclusive
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name on the sensor side
                  remote-endpoint = <&ucam_out0>;
                  //CSI2 dphy lvds number of lanes, 1 lane is <1>, 4lane is <4 >,
  must be specified
                  data-lanes = <4>;
                  //The type of LVDS interface, which must be specified
                  bus-type = <3>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // The port name of the vicap lite side
                  remote-endpoint = <&cif_lite_lvds_in>;
                  // CSI2 dphy lvds number of lanes, 1 lane is <1>, 4lane is <4 >,
  must be specified
                  data-lanes = <4>;
                  // The type of LVDS interface, which must be specified
                  bus-type = <3>;
              };
          };
      };
  };
  &rkcif_lite_mipi_lvds {
      status = "okay";
      port {
          /* lvds endpoint */
          cif_lite_lvds_in: endpoint {
              // The port name of the CSI2 dphy end
              remote-endpoint = <&csidphy0_out>;
              // CSI2 dphy lvds number of lanes, 1 lane is <1>, 4lane is <4 >, must
  be specified
              data-lanes = <4>;
              //The type of LVDS interface, which must be specified
              bus-type = <3>;
          };
      };
  };
  &rkcif_lite_sditf {
      status = "okay";
      port {
          /* lvds endpoint */
          lite_sditf: endpoint {
              //ISP virtual device port name
              remote-endpoint = <&isp_in>;
              //CSI2 dphy has the number of lanes, which is the same as the sensor
              data-lanes = <4>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &isp0_mmu {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //The endpoint name of the lite vicap lvds sditf
                  remote-endpoint = <&lite_sditf>;
              };
          };
      };
  };

If you need to use dual ISP processing, you can modify it as follows:

  &rkisp {
      status = "disabled";
  };
  &isp0_mmu {
      status = "disabled";
  };
  &rkisp_unite {
      status = "okay";
  };
  &rkisp_unite_mmu {
      status = "okay";
  };
  &rkisp0_vir0 {
      status = "okay";
      /* hw is referenced as a unite node*/
      rockchip,hw = <&rkisp_unite>;
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp0_vir0: endpoint@0 {
              reg = <0>;
              remote-endpoint = <&mipi4_lvds_sditf>;
          };
      };
  };

8.1.3 DVP interface

On the RV1126/RV1109/RK356X/RK3588 platforms, the dts configuration of each related interface of DVP is the same.

8.1.3.1.1 BT601

Taking AR0230 BT601 as an example, the link relationship is as follows:

Link relationship: sensor->vicap Configuration Essentials

hsync-active/vsync-active must be configured for the v4l2 framework to register and identify the BT601 interface asynchronously, if not configured, it will be recognized as the BT656 interface;

pclk-sample/bus-width optional;

The valid polarity of the current sensor’s hsync-acitve/vsync-active/pclk-ative must be indicated by flag in the sensor-driven g_mbus_config interface, otherwise the data will not be received;

Pinctrl needs to reference pairs to make the corresponding IOMUX for BT601-related GPIOs, otherwise it will cause data to not be received;

The sample code for the g_mbus_config interface is as follows:

  static int ar0230_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)
  {
      config->type = V4L2_MBUS_PARALLEL;
      config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
              V4L2_MBUS_VSYNC_ACTIVE_HIGH |
              V4L2_MBUS_PCLK_SAMPLE_FALLING;
      return 0;
  }

An example DTS configuration is as follows:

  ar0230: ar0230@10 {
          // It needs to match the matching string in the driver
          compatible = "aptina,ar0230";
          // sensor I2C device address, 7 bits
          reg = <0x10>;
          // Sensor mclk source configuration
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          //The sensor dependent power domain is enabled
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          power-domains = <&power RV1126_PD_VI>;
          // Powerdown pin assignment and active level
          pwdn-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
          /*reset-gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;*/
          //Configure the DVP-related data pins and clock pins
          pinctrl-names = "default";
          pinctrl-0 = <&cifm0_dvp_ctl>;
          // Module number, which should not be repeated
          rockchip,camera-module-index = <0>;
          // Module orientation, with "back" and "front"
          rockchip,camera-module-facing = "back";
          // Module name
          rockchip,camera-module-name = "CMK-OT0836-PT2";
          // Lens name
          rockchip,camera-module-lens-name = "YT-2929";
          port {
              cam_para_out1: endpoint {
                  remote-endpoint = <&cif_para_in>;
              };
          };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          /* Parallel bus endpoint */
          cif_para_in: endpoint {
              //The name of the sensor endpoint
              remote-endpoint = <&cam_para_out1>;
              //Relevant configuration parameters on the sensor side
              bus-width = <12>;
              hsync-active = <1>;
              vsync-active = <1>;
              pclk-sample = <0>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      port {
          /* parallel endpoint */
          dvp_sditf: endpoint {
              //ISP virtual device port name
              remote-endpoint = <&isp_in>;
              //Relevant configuration parameters on the sensor side
              bus-width = <12>;
              hsync-active = <1>;
              vsync-active = <1>;
              pclk-sample = <0>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //The endpoint name of the DVD SDITF
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };
8.1.3.1.2 BT656/BT1120

The BT656/BT1120 DTS usage is consistent.

Taking the Ava FPGA BT1120 as an example, the link relationship is as follows:

链接关系: sensor->vicap

配置要点

hsync-active/vsync-active do not configure, otherwise the v4l2 framework will recognize it as BT601 when registering asynchronously;

pclk-sample/bus-width optional;

The effective polarity of the current sensor’s pclk-ative must be indicated by the flag variable in the sensor- driven g_mbus_config interface, otherwise the data will not be received;

The querystd interface in the v4l2_subdev_video_ops must be implemented, indicating that the current interface is an ATSC interface, otherwise the data will not be received;

Must implement RKMODULE_GET_BT656_MBUS_INFO, BT656/BT1120 are called this ioctl, interface compatible, implementation reference drivers/media/i2c/nvp6158_drv/nvp6158_v4l2.c

Pinctrl needs to reference pairs to make IOMUX for BT656/BT1120-related GPIOs, otherwise data cannot be received.

The sample code for the g_mbus_config interface is as follows:

  static int avafpga_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)
  {
      config->type = V4L2_MBUS_BT656;
      config->flags = V4L2_MBUS_PCLK_SAMPLE_RISING;
      return 0;
  }

An example of the querystd interface is as follows:

  static int avafpga_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
  {
      *std = V4L2_STD_ATSC;
      return 0;
  }

An example DTS configuration is as follows:

  avafpga: avafpga@70 {
      // It needs to match the matching string in the driver
      compatible = "ava,fpga";
      // sensor I2C device address, 7 bits
      reg = <0x10>;
      // Sensor mclk source configuration
      clocks = <&cru CLK_CIF_OUT>;
      clock-names = "xvclk";
      //The sensor dependent power domain is enabled
      avdd-supply = <&vcc_avdd>;
      dovdd-supply = <&vcc_dovdd>;
      dvdd-supply = <&vcc_dvdd>;
      // Powerdown pin assignment and active level
      power-domains = <&power RV1126_PD_VI>;
      pwdn-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
      /*reset-gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;*/
      //Configure the DVP-related data pins and clock pins
      pinctrl-names = "default";
      pinctrl-0 = <&cifm0_dvp_ctl>;
      // Module number, which should not be repeated
      rockchip,camera-module-index = <0>;
      // Module orientation, with "back" and "front"
      rockchip,camera-module-facing = "back";
      // Module name
      rockchip,camera-module-name = "CMK-OT0836-PT2";
      // Lens name
      rockchip,camera-module-lens-name = "YT-2929";
      port {
          cam_para_out2: endpoint {
              remote-endpoint = <&cif_para_in>;
          };
      };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          /* Parallel bus endpoint */
          cif_para_in: endpoint {
              //The name of the sensor endpoint
              remote-endpoint = <&cam_para_out2>;
              //Sensor-side related configuration parameters, optional
              bus-width = <16>;
              pclk-sample = <1>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      port {
          /* parallel endpoint */
          dvp_sditf: endpoint {
              //ISP virtual device port name
              remote-endpoint = <&isp_in>;
              bus-width = <16>;
              pclk-sample = <1>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //The endpoint name of the DVD SDITF
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };
8.1.3.1.3 RV1106 DVP DTS Notes

Refer to the previous configuration description, basically unchanged, pay attention to MCLK and other hardware resources according to the actual hardware link configuration.

The RV1106 supports PINCTRLs for both DVPs, and the correct PINCTRL needs to be referenced in the DTS based on the hardware usage. M0:

Support BT1120, 16bit data Support BT656, 8bit data Support BT601, 8/10/12bit data This set of pins exists and mipi dphy pin multiplexing, mipi dphy working state to be configured in TTL mode, so rkcif_dvp node needs to reference mipi dphy node, refer to the following:

  &rkcif_dvp {
      status = "okay";
      rockchip,dphy_hw = <&csi2_dphy_hw>;
          ......

};

M1: Support BT656, 8bit data Support BT601, 8/10 data Can be used at the same time as MIPI.

Note: At present, the DVD data of the RK platform is highly aligned, and you must read the RK hardware design reference guide in detail when designing the hardware to prevent the hardware from being not designed as required and cannot be collected.

8.1.4 Multi-sensor registration

A single hardware ISP processes multiplexed multiple raw sensor data by virtualizing multiple devices.

For RV1109/RV1126/RK356X VICAP to collect DVP RAW data can only be stored as non-compact, ISP processing RAW is based on compact storage by default, for the precautions of DVP RAW data into ISP processing, please refer to How to Configure ISP/VICAP RAW Storage Format.待链接

8.1.4.1 RV1126/RV1109

The link relationship, isp0->ispp0 and isp1->ispp1 is the fixed configuration rv1126.dtsi

RV1109/RV1126 ISP/ISPP, up to 4-way multiplexing when bandwidth permits, can be added by rkisp_vir0~rkisp_vir4/rkispp_vir0~rkispp_vir4 in RV1126.DTSI

MIPI into ISP or CIF into ISP is optional.

RV1109/RV1126 supports 2 PHY interfaces, each PHY can be multiplexed as MIPI/LVDS, and supports up to 4LANE.

RV1109/RV1126 supports one DVP interface and supports BT601/BT656/BT1120.

ISP supports MIPI or DVP input: MIPI/DVP can only choose 1 of 2 and cannot work at the same time.

VICAP supports MIPI/LVDS/DVP: MIPI/LVDS is a multiplexing relationship and cannot be used at the same time, and DVP can be used at the same time as the former.

Vicap Lite only supports LVDS.

Through the understanding of the above hardware configuration, RV1109/RV1126 currently supports up to 3 RAW SENSOR input ISP processing.

8.1.4.1.1 Dual-entry ISP processing sensor0(mipi)->csi_dphy0->csi2->vicap->isp0->ispp0 sensor1(mipi)->csi_dphy1->isp1->ispp1

Example reference: arch/arm/boot/dts/rv1109-evb-ddr3-v12-facial-gate.dts gc2053->csi_dphy0->csi2->vicap->isp1->ispp1 ov2718->csi_dphy1->isp0->ispp0 For different resolutions, it is important to configure the following

&rkispp {
         status = "okay";
         /* the max input w h and fps of mulit sensor */
         max-input = <2688 1520 30>;// Maximum width and height and frame rate for different sensors
};
8.1.4.1.2 Three-entry ISP processing sensor0(mipi)->csi_dphy0->csi2->vicap->isp0->ispp0 sensor1(mipi)->csi_dphy1->isp1->ispp1 sensor2(DVP)->vicap->isp2->ispp2

or

sensor0(mipi)->csi_dphy0->csi2->vicap->isp0->ispp0 sensor1(lvds)->csi_dphy1->vicap lite->isp1->ispp1 sensor2(DVP)->vicap->isp2->ispp2

Example reference:

bf2253-0(mipi)->dphy0->csi2->vicap(mipi)->isp0->ispp0 bf2253-1(mipi)->dphy1->isp1->ispp1 gc1054(dvp)->vicap(dvp)->isp2->ispp2

  &i2c1 {
      status = "okay";
       clock-frequency = <400000>;
      gc1054: gc1054@21 {
                 compatible = "galaxycore,gc1054";
              reg = <0x21>;
                 clocks = <&cru CLK_CIF_OUT>;
              clock-names = "xvclk";
              power-domains = <&power RV1126_PD_VI>;
              pwdn-gpios  = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>;
              reset-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
              rockchip,grf = <&grf>;
              pinctrl-names = "default";
              pinctrl-0 = <&cifm0_dvp_ctl>;
              rockchip,camera-module-index = <0>;
              rockchip,camera-module-facing = "back";
              rockchip,camera-module-name = "GC1054_B";
              rockchip,camera-module-lens-name = "GC1054_LEN";
                 port {
                      cam_para_out1: endpoint {
                      remote-endpoint = <&cif_para_in>;
                          bus-width = <10>;
                          hsync-active = <1>;
                          vsync-active = <1>;
              };
          };
      };
      bf2253_isp0: bf2253_isp0@6d {
            compatible = "ovti,bf2253_isp0";
            reg = <0x6d>;
            clocks = <&cru CLK_MIPICSI_OUT>;
            clock-names = "xvclk";
            power-domains = <&power RV1126_PD_VI>;
            pinctrl-names = "rockchip,camera_default";
            pinctrl-0   = <&mipicsi_clk0>;
            power-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
            pwdn-gpios  = <&gpio1 RK_PD4 GPIO_ACTIVE_LOW>;
            reset-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
            avdd-supply  = <&vcc_3v3>;
            dovdd-supply = <&vcc_1v8>;
            dvdd-supply  = <&vcc_1v8>;
            rockchip,camera-module-index = <1>;
            rockchip,camera-module-facing = "front";
            rockchip,camera-module-name = "LA6110PA";
            rockchip,camera-module-lens-name = "YM6011P";
            port {
                cam_out1: endpoint {
                      remote-endpoint = <&mipi_in_ucam>;
                      data-lanes = <1>;
                  };
            };
       };
  };
  &i2c3 {
      status = "okay";
      clock-frequency = <400000>;
      pinctrl-names = "default";
      pinctrl-0 = <&i2c3m2_xfer>;
      bf2253_isp1: bf2253_isp1@6d {
            compatible = "ovti,bf2253_isp1";
            reg = <0x6d>;
            clocks = <&cru CLK_MIPICSI_OUT>;
            clock-names = "xvclk";
            power-domains = <&power RV1126_PD_VI>;
            pinctrl-names = "rockchip,camera_default";
            //pinctrl-names = "rockchip,camera_sleep";
            pinctrl-0 = <&mipicsi_clk1>;
            power-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
            pwdn-gpios  = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>;
            reset-gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>;
            avdd-supply  = <&vcc_3v3>;
            dovdd-supply = <&vcc_1v8>;
            dvdd-supply  = <&vcc_1v8>;
            rockchip,camera-module-index = <2>;
            rockchip,camera-module-facing = "front";
            rockchip,camera-module-name = "LA6110PA";
            rockchip,camera-module-lens-name = "YM6011P";
            port {
                 cam_out0: endpoint {
                     remote-endpoint = <&csi_dphy1_input>;
                     data-lanes = <1>;
                 };
            };
       };
  };
  &csi_dphy0 {
      status = "okay";
      ports {
          port@0 {
              mipi_in_ucam: endpoint@1 {
                  remote-endpoint = <&cam_out1>;
                  data-lanes = <1>;
              };
          };
          port@1 {
              csi_dphy0_out: endpoint@0 {
                  remote-endpoint = <&mipi_csi2_input>;
                  data-lanes = <1>;
              };
          };
      };
  };
  &csi_dphy1 {
      status = "okay";
      ports {
          port@0 {
              csi_dphy1_input: endpoint@1 {
                  remote-endpoint = <&cam_out0>;
                  data-lanes = <1>;
              };
          };
          port@1 {
              csi_dphy1_output: endpoint@0 {
                  remote-endpoint = <&isp_in1>;
                  data-lanes = <1>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          port@0 {
              mipi_csi2_input: endpoint@1 {
                  remote-endpoint = <&csi_dphy0_out>;
                  data-lanes = <1>;
              };
          };
          port@1 {
              mipi_csi2_output: endpoint@0 {
                  remote-endpoint = <&cif_mipi_in>;
                  data-lanes = <1>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          lvds_sditf: endpoint {
              remote-endpoint = <&isp_in0>;
              data-lanes = <1>;
          };
      };
  };
  &rkcif_dvp {
          status = "okay";
          //iommus = <&rkcif_mmu>;
          ///delete-property/ memory-region;
          port {
                  /* Parallel bus endpoint */
                  cif_para_in: endpoint {
                          remote-endpoint = <&cam_para_out1>;
                          bus-width = <8>;
                          hsync-active = <1>;
                          vsync-active = <1>;
                  };
          };
  };
  &rkcif_dvp_sditf {
          status = "okay";
          port {
                  /* Parallel bus endpoint */
          dvp_sditf: endpoint {
                          remote-endpoint = <&isp_in2>;
                  };
          };
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in0: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&lvds_sditf>;
              };
          };
      };
  };
  &rkisp_vir1 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in1: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&csi_dphy1_output>;
              };
          };
      };
  };
  &rkisp_vir2 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in2: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };
  &rkispp_vir0 {
      status = "okay";
  };
  &rkispp_vir1 {
      status = "okay";
  };
  &rkispp_vir2 {
          status = "okay";
  };
  &rkcif {
          status = "okay";
  };
  rkisp: rkisp@ffb50000 {
      status = "okay";
  };
  &rkispp {
      status = "okay";
      max-input = <1600 1200 30>;
      memory-region = <&isp_reserved>;
      /* the max input w h and fps of mulit sensor */
  };
   rkcif_mmu: iommu@ffae0800{
      status = "disabled";
  };
   rkisp_mmu: iommu@ffb51a00 {
      status = "disabled";
  };
  &rkispp_mmu {
      status = "disabled";
  };
8.1.4.2 RK3566/RK3568

RK356X ISP, up to 4 multiplexed when bandwidth allows, can be added by rkisp_vir0~rkisp_vir4 in RK3568.DTSI

MIPI into ISP or CIF into ISP is optional.

The RK356X supports 1 4-lane PHY interface, which can be divided into 2 2-lane PHYs. The rk356x supports one DVD interface and supports BT601/BT656/BT1120 ISP supports MIPI or DVP input: MIPI/DVP can only choose 1 of 2 and cannot work at the same time. VICAP supports MIPI/DVP: MIPI and DVP can be used at the same time. Through the understanding of the above hardware configuration, the RK356X currently supports up to 3 RAW SENSORS into ISP processing.

8.1.4.2.1 Dual Intake ISP Processing:

Reference examples:

ov5695->dphy1->isp_vir0 gc5025->dphy2->csi2->vicap->isp_vir1

  ov5695: ov5695@36 {
          status = "okay";
          ...
          port {
              ov5695_out: endpoint {
                  remote-endpoint = <&dphy1_in>;
                  data-lanes = <1 2>;
              };
          };
  };
  gc5025: gc5025@37 {
          status = "okay";
          ...
          port {
              gc5025_out: endpoint {
                  remote-endpoint = <&dphy2_in>;
                  data-lanes = <1 2>;
              };
          };
  };
   &csi2_dphy_hw {
           status = "okay";
   };
  &csi2_dphy1 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&ov5695_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&isp0_in>;
              };
          };
      };
  };
  &csi2_dphy2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&gc5025_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&dphy2_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&cif_mipi_in>;
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          mipi_lvds_sditf: endpoint {
              remote-endpoint = <&isp1_in>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkisp {
      status = "okay";
      /* the max input w h and fps of mulit sensor */
      max-input = <2592 1944 30>;
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp0_in: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&dphy1_out>;
              };
          };
      };
  };
  &rkisp_vir1 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp1_in: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };
8.1.4.2.2 Three-shot ISP Processing:

Reference examples:

gc2053(mipi)->dphy1->isp0 sc1330(dvp)->vicap(dvp)->isp1 ov5695(mipi)->dphy2->csi2->vicap(mipi)->isp2

  &i2c2 {
      status = "okay";
      pinctrl-0 = <&i2c2m1_xfer>;
      /* split mode: lane0/1 */
      gc2053: gc2053@37 {
          status = "okay";
          compatible = "galaxycore,gc2053";
          reg = <0x37>;
          clocks = <&cru CLK_CAM0_OUT>;
          clock-names = "xvclk";
          /* Set pinctl of xvclk in &pinctl */
          power-domains = <&power RK3568_PD_VI>;
          reset-gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_LOW>;
          pwdn-gpios = <&gpio3 RK_PD0 GPIO_ACTIVE_LOW>;
          /*power-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;*/
          rockchip,camera-module-index = <0>;
          rockchip,camera-module-facing = "front";
          rockchip,camera-module-name = "rgbd";
          rockchip,camera-module-lens-name = "Optics";
          port {
              gc2053_out: endpoint {
                  remote-endpoint = <&dphy1_in>;
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &i2c3 {
      status = "okay";
      pinctrl-0 = <&i2c3m0_xfer>;
      sc1330: sc1330@32 {
          status = "okay";
          compatible = "smartsens,sc1330";
          reg = <0x32>;
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          power-domains = <&power RK3568_PD_VI>;
          pinctrl-names = "default";
          /* conflict with gmac1m1_rgmii_pins & cif_clk*/
          pinctrl-0 = <&cif_clk &cif_dvp_clk &cif_dvp_bus10>;
          /*avdd-supply = <&vcc2v8_dvp>;*/
          /*dovdd-supply = <&vcc1v8_dvp>;*/
          /*dvdd-supply = <&vcc1v8_dvp>;*/
          reset-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_LOW>;
          pwdn-gpios = <&gpio3 RK_PC7 GPIO_ACTIVE_LOW>;
          rockchip,camera-module-index = <2>;
          rockchip,camera-module-facing = "back";
          rockchip,camera-module-name = "default";
          rockchip,camera-module-lens-name = "default";
          port {
              sc1330_out: endpoint {
                  remote-endpoint = <&dvp_in_bcam>;
              };
          };
      };
  };
  &i2c4 {
      status = "okay";
      pinctrl-0 = <&i2c4m0_xfer>;
      clock-frequency = <1000000>;
      /* split mode: lane:2/3 */
      ov5695: ov5695@36 {
                  status = "okay";
                  compatible = "ovti,ov5695";
                  reg = <0x36>;
                  clocks = <&cru CLK_CAM0_OUT>;
                  clock-names = "xvclk";
                  power-domains = <&power RK3568_PD_VI>;
                  pinctrl-names = "default";
                  pinctrl-0 = <&cif_clk>;
                  reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
                  pwdn-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
                  rockchip,camera-module-index = <1>;
                  rockchip,camera-module-facing = "front";
                  rockchip,camera-module-name = "TongJu";
                  rockchip,camera-module-lens-name = "CHT842-MD";
                  port {
                          ov5695_out: endpoint {
                                  remote-endpoint = <&dphy2_in>;
                                  data-lanes = <1 2>;
                          };
                  };
      };
  };
  &csi2_dphy_hw {
      status = "okay";
  };
  &csi2_dphy1 {
      status = "okay";
      /*
       * dphy1 only used for split mode,
       * can be used  concurrently  with dphy2
       * full mode and split mode are mutually exclusive
       */
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&gc2053_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&isp0_in>;
              };
          };
      };
  };
  &csi2_dphy2 {
      status = "okay";
      /*
       * dphy2 only used for split mode,
       * can be used  concurrently  with dphy1
       * full mode and split mode are mutually exclusive
       */
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&ov5695_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&dphy2_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&cif_mipi_in>;
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif {
      status = "okay";
  };
  &rkcif_mmu {
      status = "okay";
  };
  &rkcif_mipi_lvds {
      status = "okay";
      /* csi2 link to rkcif, using rkcif to capture stream */
      port {
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          mipi_lvds_sditf: endpoint {
              remote-endpoint = <&isp2_in>;
          };
      };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          dvp_in_bcam: endpoint {
              remote-endpoint = <&sc1330_out>;
              bus-width = <10>;
              vsync-active = <0>;
              hsync-active = <1>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      /* parallel endpoint */
      port {
          dvp_sditf: endpoint {
              remote-endpoint = <&isp1_in>;
              bus-width = <10>;
              pclk-sample = <1>;
          };
      };
  };
  &rkisp {
      status = "okay";
      /* the max input w h and fps of mulit sensor */
      max-input = <1920 1080 30>;
  };
  &rkisp_mmu {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp0_in: endpoint@0 {
              reg = <0>;
              remote-endpoint = <&dphy1_out>;
          };
      };
  };
  &rkisp_vir1 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp1_in: endpoint@0 {
              reg = <0>;
              remote-endpoint = <&dvp_sditf>;
          };
      };
  };
  &rkisp_vir2 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp2_in: endpoint@0 {
              reg = <0>;
              remote-endpoint = <&mipi_lvds_sditf>;
          };
      };
  };
8.1.4.3 RK3588

1. Refer to RK3588 Multisensor Support instructions待链接

2. Refer to arch/arm64/boot/dts/rockchip/rk3588-evb1-cam-6x.dtsi

3. For dual ISP unite mode

1)Support dual camera, maximum resolution 7424x2160

2)Support 3/4 camera, maximum resolution 4864x1536

The DTS configuration is described in the above unite mode single-camera configuration description, and then configured as follows: ISP nodes

&rkisp0_vir1 {
     status = "okay";
     rockchip,hw = <&rkisp_unite>;
   //Other omissions
};
&rkisp0_vir2 {
     status = "okay";
     rockchip,hw = <&rkisp_unite>;
   //Other omissions
};
8.1.4.4 RV1106

dts reference arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi

Hardware ISP support dual camera, the maximum resolution is 1080p, if it is larger than this resolution, it needs to be processed by a single frame 2 readback, the disadvantages consume more ISP throughput, bandwidth increases, and the output frame rate is low.

8.1.4.5 RK3562

dts reference arch/arm64/boot/dts/rockchip/rk3562-evb2-ddr4-v10-dual-camera.dts

dual camera, the maximum resolution is 3840x2160

three camera, the maximum resolution is 3840x2160 2688x1536 and 2688x1536

four camera, the maximum resolution is 2688x1536

8.2 CIS driver description

Camera sensor uses I2C to interact with the main control, and the sensor driver is currently implemented in accordance with the I2C device driver mode, and the sensor driver also uses the V4l2 subdev method to realize the interaction with the host driver.

8.2.1 A brief description of the data type

8.2.1.1 struct i2c_driver

[Description]

Define I2C device driver information

[Definition]

  struct i2c_driver {
      ……
      /* Standard driver model interfaces */
      int (*probe)(struct i2c_client *, const struct i2c_device_id *);
      int (*remove)(struct i2c_client *);
      ……
      struct device_driver driver;
      const struct i2c_device_id *id_table;
      ……
  };

[Key Member]

Member name description
@driver The Device driver model driver mainly contains the driver name and the of_match_table that matches the DTS registered device. The .probe function is called when the compatible field in the of_match_table matches the compatible field of the DTS file
@id_table List of I2C devices supported by this driver If the kernel does not use of_match_table and dts registered devices for matching, the kernel uses that table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  #if IS_ENABLED(CONFIG_OF)
  static const struct of_device_id os04a10_of_match[] = {
      { .compatible = "ovti,os04a10" },
      {},
  };
  MODULE_DEVICE_TABLE(of, os04a10_of_match);
  #endif
  static const struct i2c_device_id os04a10_match_id[] = {
      { "ovti,os04a10", 0 },
      { },
  };
  static struct i2c_driver os04a10_i2c_driver = {
      .driver = {
          .name = OS04A10_NAME,
          .pm = &os04a10_pm_ops,
          .of_match_table = of_match_ptr(os04a10_of_match),
      },
      .probe        = &os04a10_probe,
      .remove        = &os04a10_remove,
      .id_table    = os04a10_match_id,
  };
  static int __init sensor_mod_init(void)
  {
      return i2c_add_driver(&os04a10_i2c_driver);
  }
  static void __exit sensor_mod_exit(void)
  {
      i2c_del_driver(&os04a10_i2c_driver);
  }
  device_initcall_sync(sensor_mod_init);
  module_exit(sensor_mod_exit);
8.2.1.2 struct v4l2_subdev_ops

[Description]

Define ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_ops {
      const struct v4l2_subdev_core_ops    *core;
      ……
      const struct v4l2_subdev_video_ops    *video;
      ……
      const struct v4l2_subdev_pad_ops    *pad;
  };

[Key Member]

Member name description
.core Define core ops callbacks for subdevs
.video Callbacks used when v4l device was opened in video mode.
.pad v4l2-subdev pad level operations

[Example]

  static const struct v4l2_subdev_ops os04a10_subdev_ops = {
      .core    = &os04a10_core_ops,
      .video    = &os04a10_video_ops,
      .pad    = &os04a10_pad_ops,
  };
8.2.1.3 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      int (*s_power)(struct v4l2_subdev *sd, int on);
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
          unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name description
.s_power puts subdevice in power saving mode (on == 0) or normal operation mode (on == 1).
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops os04a10_core_ops = {
      .s_power = os04a10_s_power,
      .ioctl = os04a10_ioctl,
  #ifdef CONFIG_COMPAT
      .compat_ioctl32 = os04a10_compat_ioctl32,
  #endif
  };

Currently, the following private IOCTL is used to query module information and set up OTP information.

Private ioctl description
RKMODULE_GET_MODULE_INFO For module information, refer to struct rkmodule_inf;
RKMODULE_AWB_CFG The compensation function of the switch sensor to AWB; If the module does not flash the golden awb value, you can set this setting; Refer to struct rkmodule_awb_cfg;
RKMODULE_LSC_CFG Switch sensor compensation function for LSC; Detailed refer tostruct rkmodule_lsc_cfg;
PREISP_CMD_SET_HDRAE_EXP HDR exposure settings are detailed refer tostruct preisp_hdrae_exp_s
RKMODULE_SET_HDR_CFG Setting HDR mode can switch between normal and HDR mode, and you need to refer to the configuration information of the driver adaptation normal and HDR 2 groups for detailed refer tostruct rkmodule_hdr_cfg
RKMODULE_GET_HDR_CFG Get a detailed reference to the current HDR mode struct rkmodule_hdr_cfg
RKMODULE_SET_CONVERSION_GAIN Set the conversion gain of linear mode, such as IMX347, OS04A10 sensor with conversion gain function, such as the sensor does not support conversion gain, can not be implemented
8.2.1.4 struct v4l2_subdev_video_ops

[Description]

Callbacks used when v4l device was opened in video mode.

[Definition]

  struct v4l2_subdev_video_ops {
      ……
      int (*s_stream)(struct v4l2_subdev *sd, int enable);
      ……
      int (*g_frame_interval)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_frame_interval *interval);
      int (*g_mbus_config)(struct v4l2_subdev *sd,
                 struct v4l2_mbus_config *cfg);
   ……
  };

[Key Member]

Member name description
.g_frame_interval callback for VIDIOC_SUBDEV_G_FRAME_INTERVAL ioctl handler code
.s_stream used to notify the driver that a video stream will start or has stopped
.g_mbus_config get supported mediabus configurations

[Example]

  static const struct v4l2_subdev_video_ops os04a10_video_ops = {
      .s_stream = os04a10_s_stream,
      .g_frame_interval = os04a10_g_frame_interval,
      .g_mbus_config = os04a10_g_mbus_config,
  };
8.2.1.5 struct v4l2_subdev_pad_ops

[Description]

v4l2-subdev pad level operations

[Definition]

  struct v4l2_subdev_pad_ops {
      ……
      int (*enum_mbus_code)(struct v4l2_subdev *sd,
                 struct v4l2_subdev_pad_config *cfg,
                 struct v4l2_subdev_mbus_code_enum *code);
      int (*enum_frame_size)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_frame_size_enum *fse);
      int (*get_fmt)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_format *format);
      int (*set_fmt)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_format *format);
      int (*enum_frame_interval)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_frame_interval_enum *fie);
      int (*get_selection)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_selection *sel);
      ……
  };

[Key Member]

Member name description
. enum_mbus_code callback for VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl handler code.
. enum_frame_size callback for VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl handler code.
.s_fmt callback for VIDIOC_SUBDEV_S_FMT ioctl handler code.
.g_fmt callback for VIDIOC_SUBDEV_G_FMT ioctl handler code
.enum_frame_interval callback for VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL() ioctl handler code.
.get_selection callback for VIDIOC_SUBDEV_G_SELECTION() ioctl handler code.

[Example]

  static const struct v4l2_subdev_pad_ops os04a10_pad_ops = {
      .enum_mbus_code = os04a10_enum_mbus_code,
      .enum_frame_size = os04a10_enum_frame_sizes,
      .enum_frame_interval = os04a10_enum_frame_interval,
      .get_fmt = os04a10_get_fmt,
      .set_fmt = os04a10_set_fmt,
  };
8.2.1.6 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name description
.s_ctrl actually set the new control value.

[Example]

  static const struct v4l2_ctrl_ops os04a10_ctrl_ops = {
      .s_ctrl = os04a10_set_ctrl,
  };

The RKISP driver requires the use of the user controls function provided by the framework, and the cameras sensor driver must implement the following control functions,refer to:CIS驱动V4L2-controls列表1待链接

8.2.1.7 struct xxxx_mode

[Description]

The Sensor can support information in each mode.

This structure is often seen in sensor drivers, although it is not required by the V4L2 standard. As functionality increases, the structure can add variables according to demand.

[Definition]

  struct xxxx_mode {
      u32 bus_fmt;
      u32 width;
      u32 height;
      struct v4l2_fract max_fps;
      u32 hts_def;
      u32 vts_def;
      u32 exp_def;
      const struct regval *reg_list;
      u32 hdr_mode;
      u32 vc[PAD_MAX];
  };

[Key Member]

Member name description
.bus_fmt Sensor output format, refer toMEDIA_BUS_FMT 表 待链接
.width The effective image width needs to be consistent with the width output currently configured by the sensor
.height The effective image height needs to be consistent with the HEIGHT output currently configured by the sensor
.max_fps Image FPS, denominator/numerator is fps
hts_def The default HTS is effective image width + HBLANK
vts_def The default VTS is valid image height + VBLANK
exp_def Default exposure time
*reg_list List of registers
.hdr_mode Sensor working mode, support linear mode, two-frame composite HDR, three-frame synthetic HDR
.vc[PAD_MAX] Configure the MIPI VC channel

[Example]

   enum os04a10_max_pad {
      PAD0, /* link to isp */
      PAD1, /* link to csi rawwr0 | hdr x2:L x3:M */
      PAD2, /* link to csi rawwr1 | hdr    x3:L */
      PAD3, /* link to csi rawwr2 | hdr x2:M x3:S */
      PAD_MAX,
  };
  static const struct os04a10_mode supported_modes[] = {
      {
          .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
          .width = 2688,
          .height = 1520,
          .max_fps = {
              .numerator = 10000,
              .denominator = 300372,
          },
          .exp_def = 0x0240,
          .hts_def = 0x05c4 * 2,
          .vts_def = 0x0984,
          .reg_list = os04a10_linear12bit_2688x1520_regs,
          .hdr_mode = NO_HDR,
          .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
      }, {
          .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
          .width = 2688,
          .height = 1520,
          .max_fps = {
              .numerator = 10000,
              .denominator = 225000,
          },
          .exp_def = 0x0240,
          .hts_def = 0x05c4 * 2,
          .vts_def = 0x0658,
          .reg_list = os04a10_hdr12bit_2688x1520_regs,
          .hdr_mode = HDR_X2,
          .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
          .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
          .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
          .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
      },
  };
8.2.1.8 struct v4l2_mbus_framefmt

[Description]

frame format on the media bus

[Definition]

  struct v4l2_mbus_framefmt {
      __u32            width;
      __u32            height;
      __u32            code;
      __u32            field;
      __u32            colorspace;
      __u16            ycbcr_enc;
      __u16            quantization;
      __u16            xfer_func;
      __u16            reserved[11];
  };

[Key Member]

Member name description
width Frame width
height Frame height
code Refer toMEDIA_BUS_FMT 表
field V4L2_FIELD_NONE: Frame output mode V4L2_FIELD_INTERLACED: Field output mode

[Example]

8.2.1.9 struct rkmodule_base_inf

[Description]

The basic information of the module, the upper layer uses this information to match with IQ

[Definition]

  struct rkmodule_base_inf {
      char sensor[RKMODULE_NAME_LEN];
      char module[RKMODULE_NAME_LEN];
      char lens[RKMODULE_NAME_LEN];
  } __attribute__ ((packed));

[Key Member]

Member name description
sensor The name of the sensor, obtained from the sensor driver
module The module name is obtained from the DTS configuration, and the module information shall prevail
lens The lens name, obtained from the DTS configuration, is subject to the module data

[Example]

8.2.1.10 struct rkmodule_fac_inf

[Description]

Module OTP factory information

[Definition]

  struct rkmodule_fac_inf {
      __u32 flag;
      char module[RKMODULE_NAME_LEN];
      char lens[RKMODULE_NAME_LEN];
      __u32 year;
      __u32 month;
      __u32 day;
  } __attribute__ ((packed));

[Key Member]

Member name description
flag The identity of whether the group information is valid
module Module name, get the number from the OTP, and get the module name from the number
lens Lens name, get the number from the OTP, and get the lens name from the number
year Year of production, such as 12 for 2012
month Production month
day Production date

[Example]

8.2.1.11 struct rkmodule_awb_inf

[Description]

Module OTP awb measurement information

[Definition]

  struct rkmodule_awb_inf {
      __u32 flag;
      __u32 r_value;
      __u32 b_value;
      __u32 gr_value;
      __u32 gb_value;
      __u32 golden_r_value;
      __u32 golden_b_value;
      __u32 golden_gr_value;
      __u32 golden_gb_value;
  } __attribute__ ((packed));

[Key Member]

Member name description
flag The identity of whether the group information is valid
r_value AWB R measurement information for the current module
b_value AWB B measurement information for the current module
gr_value AWB GR measurement information for the current module
gb_value AWB GB measurement information for the current module
golden_r_value The AWB R measurement information of a typical module, if not burned, is set to 0
golden_b_value The AWB B measurement information of a typical module, if not burned, is set to 0
golden_gr_value The AWB GR measurement information of a typical module, if not burned, is set to 0
golden_gb_value The AWB GB measurement information of a typical module, if not burned, is set to 0

[Example]

8.2.1.12 struct rkmodule_lsc_inf

[Description]

Module OTP lsc measurement information

[Definition]

  struct rkmodule_lsc_inf {
      __u32 flag;
      __u16 lsc_w;
      __u16 lsc_h;
      __u16 decimal_bits;
      __u16 lsc_r[RKMODULE_LSCDATA_LEN];
      __u16 lsc_b[RKMODULE_LSCDATA_LEN];
      __u16 lsc_gr[RKMODULE_LSCDATA_LEN];
      __u16 lsc_gb[RKMODULE_LSCDATA_LEN];
  } __attribute__ ((packed));

[Key Member]

Member name description
flag The identity of whether the group information is valid
lsc_w The actual width of the LSC table
lsc_h LSC table actual height
decimal_bits The number of decimal places in the LSC measurement information is set to 0 if it cannot be obtained
lsc_r LSC R assay information
lsc_b LSC B assay information
lsc_gr LSC GR assay information
lsc_gb LSC GB assay information

[Example]

8.2.1.13 struct rkmodule_af_inf

[Description]

Module OTP af measurement information

[Definition]

  struct rkmodule_af_inf {
      __u32 flag; // The identity of whether the group information is valid
      __u32 vcm_start; // VCM start-up current
      __u32 vcm_end; // VCM terminates the current
      __u32 vcm_dir; // VCM determination direction
  } __attribute__ ((packed));

[Key Member]

Member name description
flag The identity of whether the group information is valid
vcm_start VCM start-up current
vcm_end VCM terminates the current
vcm_dir VCM determination direction

[Example]

8.2.1.14 struct rkmodule_inf

[Description]

Module information

[Definition]

  struct rkmodule_inf {
      struct rkmodule_base_inf base;
      struct rkmodule_fac_inf fac;
      struct rkmodule_awb_inf awb;
      struct rkmodule_lsc_inf lsc;
      struct rkmodule_af_inf af;
  } __attribute__ ((packed));

[Key Member]

Member name description
base Basic module information
fac Module OTP factory information
awb Module OTP awb measurement information
lsc Module OTP lsc measurement information
af Module OTP af measurement information

[Example]

8.2.1.15 struct rkmodule_awb_cfg

[Description]

Module OTP awb configuration information

[Definition]

  struct rkmodule_awb_cfg {
      __u32 enable;
      __u32 golden_r_value;
      __u32 golden_b_value;
      __u32 golden_gr_value;
      __u32 golden_gb_value;
  } __attribute__ ((packed));

[Key Member]

Member name description
enable Identifies whether AWB correction is enabled
golden_r_value AWB R measurement information for a typical module
golden_b_value AWB B determination information for a typical module
golden_gr_value Information on AWB GR determination of a typical module
golden_gb_value AWB GB measurement information for typical modules

[Example]

8.2.1.16 struct rkmodule_lsc_cfg

[Description]

[Definition]

[Key Member]

[Example]

[Description]

[Definition]

[Key Member]

[Example]

9. Chip version different

SOC VI IP VI Interface Bayer CIS max resolution Feature
RV1109 ISP20 ( ISP + ISPP): 1 VICAP Full: 1 VICAP Lite: 1 MIPI DPHY: 2 x 4Lanes 2.5Gbps/Lane LVDS: 2 x 4Lanes 1.0Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 3072x2048 Upto 3 frames HDR
RK3566 ISP21 Lite: 1 VICAP Full: 1 MIPI DPHY: 2 x 2Lanes or 1 x 4Lanes 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4096x3072 No HDR
RK3568 ISP21:1 VICAP Full: 1 MIPI DPHY: 2 x 2Lanes or 1 x 4Lanes 2.5Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4096x3072 Upto 2 frames HDR
RV1126 ISP20 ( ISP + ISPP): 1 VICAP Full: 1 VICAP Lite: 1 MIPI DPHY: 2 x 4Lanes 2.5Gbps/Lane LVDS: 2 x 4Lanes 1.0Gbps/Lane DVP: BT601 / BT656 / BT1120 pclk: 150MHz 4416x3312 Upto 3 frames HDR

10. CIS (cmos image sensor) driver

10.1 CIS Device Registration (DTS)

10.1.1 Single registration

10.1.1.1 MIPI interface

For the RV1126 and RV1106 platforms, there are two independent and complete standard physical mipi csi2 dphys, corresponding to csi_dphy0 and csi_dphy1 on dts (see RV1126.dtsi), the characteristics are as follows:

The maximum data lane is 4 lanes;

The maximum rate is 2.5Gbps/lane;

For the RK356X platform, there is only one standard physical mipi csi2 dphy, which can work in two modes: full mode and split mode, which can be split into three logical dphys (see rk3568.dtsi): csi2_dphy0/csi2_dphy1/csi2_dphy2 (see rk3568.dtsi). The features are as follows:

Full mode

Only use csi2_dphy0, csi2_dphy0 and csi2_dphy1/csi2_dphy2 are mutually exclusive and cannot be used at the same time;

The maximum data lane is 4 lanes;

The maximum rate is 2.5Gbps/lane;

Split mode

Only use csi2_dphy1 and csi2_dphy2, mutually exclusive with csi2_dphy0, and cannot be used at the same time;

csi2_dphy1 and csi2_dphy2 can be used at the same time;

The maximum data lane of csi2_dphy1 and csi2_dphy2 is 2 lanes;

csi2_dphy1 corresponds to lane0/lane1 of the physical dphy;

csi2_dphy2 corresponds to lane2/lane3 of physical dphy;

Maximum rate 2.5Gbps/lane

For specific dts use cases, see the following examples.

RV1126/RV1106 platform

Take RV1126 isp and os04a10 as examples below.

Link relationship: sensor->csi_dphy->isp->ispp

arch/arm/boot/dts/RV1126-evb-v10.dtsi

Configuration points

data-lanes must specify the number of lanes used, otherwise it will not be recognized as mipi type;

  cam_ircut0: cam_ircut {
      status = "okay";
      compatible = "rockchip,ircut";
      ircut-open-gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_HIGH>;
      ircut-close-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
      rockchip,camera-module-index = <1>;
      rockchip,camera-module-facing = "front";
  };
  os04a10: os04a10@36 {
      // Need to be consistent with the matching string in the driver
      compatible = "ovti,os04a10";
      reg = <0x36>;// sensor I2CDevice address, 7 bits
      clocks = <&cru CLK_MIPICSI_OUT>;// sensor clickinConfiguration
      clock-names = "xvclk";
      power-domains = <&power RV1126_PD_VI>;
      pinctrl-names = "rockchip,camera_default";
      pinctrl-0 = <&mipi_csi_clk0>;// pinctl Set up
      //power supply
      avdd-supply = <&vcc_avdd>;
      dovdd-supply = <&vcc_dovdd>;
      dvdd-supply = <&vcc_dvdd>;
      // power Pin assignment and effective level
      pwdn-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
      // Module number, this number should not be repeated
      rockchip,camera-module-index = <1>;
      // Module orientation which are "back" and "front"
      rockchip,camera-module-facing = "front";
      // name of moudle
      rockchip,camera-module-name = "CMK-OT1607-FV1";
      // lens name
      rockchip,camera-module-lens-name = "M12-4IR-4MP-F16";
      //ir cut device
      ir-cut = <&cam_ircut0>;
      port {
          ucam_out0: endpoint {
              // mipi dphy port
              remote-endpoint = <&mipi_in_ucam0>;
              // number of mipi lane,1lane is <1>, 4lanei s <1 2 3 4>
              data-lanes = <1 2 3 4>;
          };
      };
   };
  &csi_dphy0 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&ucam_out0>;
                  // mipi lane number,1lane is <1>, 4lane is <1 2 3 4>
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // name of isp port
                  remote-endpoint = <&isp_in>;
              };
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  // name of mipi dphy port
                  remote-endpoint = <&csidphy0_out>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp0_out: endpoint@1 {
                  reg = <1>;
                  // ispp port name, isp output to ispp
                  remote-endpoint = <&ispp0_in>;
              };
          };
      };
  };
  &rkispp {
      status = "okay";
  };
  &rkispp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          Ispp0_in: endpoint@0 {
              reg = <0>;
              // isp port name, ispp input
              remote-endpoint = <&isp0_out>;
          };
      };
  };

RK356X platform

Let’s take rk3566 isp and gc8034 4lane as examples for description:

Link relationship: sensor->csi2_dphy0->isp Configuration points

Need to configure data-lanes

Need to enable csi2_dphy_hw node

      /* full mode: lane0-3 */
      gc8034: gc8034@37 {
          //Need to be consistent with the matching string in the driver
          compatible = "galaxycore,gc8034";
          status = "okay";
          // sensor I2C device address, 7 bits
          reg = <0x37>;
          // sensor mclk Source configuration
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          power-domains = <&power RK3568_PD_VI>;
          //sensor mclk pinctl set up
          pinctrl-names = "default";
          pinctrl-0 = <&cif_clk>;
          // resetPin assignment and effective level
          reset-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_LOW>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <0>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "back";
          // moudle name
          rockchip,camera-module-name = "RK-CMK-8M-2-v1";
          // lens name
          rockchip,camera-module-lens-name = "CK8401";
          port {
              gc8034_out: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&dphy0_in>;
                  // csi2 dphy lane number,1lane is <1>, 4lane is <1 2 3 4>
                  data-lanes = <1 2 3 4>;
              };
          };
      };
      &csi2_dphy_hw {
         status = "okay";
      };
      &csi2_dphy0 {
          //csi2_dphy0 is not used simultaneously with csi2_dphy1/csi2_dphy2, mutually exclusive
          status = "okay";
          /*
           * dphy0 only used for full mode,
           * full mode and split mode are mutually exclusive
           */
          ports {
              #address-cells = <1>;
              #size-cells = <0>;
              port@0 {
                  reg = <0>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  dphy0_in: endpoint@1 {
                      reg = <1>;
                      // The port name of the sensor
                      remote-endpoint = <&gc8034_out>;
                      // csi2 dphy lane number
                      data-lanes = <1 2 3 4>;
                  };
              };
              port@1 {
                  reg = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  dphy0_out: endpoint@1 {
                      reg = <1>;
                      // The port name of the isp
                      remote-endpoint = <&isp0_in>;
                  };
              };
          };
      };
  &rkisp {
      status = "okay";
  };
  &rkisp_mmu {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp0_in: endpoint@0 {
              reg = <0>;
              // The port name of csi2 dphy
              remote-endpoint = <&dphy0_out>;
          };
      };
  };

RV1126/RV1109 platform

Take mipi os04a10 4lane link vicap as an example:

Link relationship: sensor->csi dphy->mipi csi host->vicap Configuration points:

data-lanes must specify the number of lanes used, otherwise it will not be recognized as mipi type;

dphy needs to be linked to the csi host node.

  os04a10: os04a10@36 {
          // Need to be consistent with the matching string in the driver
          compatible = "ovti,os04a10";
          // sensor I2C device address, 7 bits
          reg = <0x36>;
          // sensor mclkSource configuration
          clocks = <&cru CLK_MIPICSI_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          power-domains = <&power RV1126_PD_VI>;
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          //sensor mclk pinctlset up
          pinctrl-names = "rockchip,camera_default";
          pinctrl-0 = <&mipicsi_clk0>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "front";
          // module name
          rockchip,camera-module-name = "CMK-OT1607-FV1";
          // lens name
          rockchip,camera-module-lens-name = "M12-40IRC-4MP-F16";
          // ircut name
          ir-cut = <&cam_ircut0>;
          port {
              ucam_out0: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&mipi_in_ucam0>;
                  // csi2 dphy lane number,1lane is <1>, 4lane is  <1 2 3 4>
                  data-lanes = <1 2 3 4>;
              };
          };
      };
  &csi_dphy0 {
      //csi2_dphy0 is not simultaneous use with csi2_dphy1/csi2_dphy2 , mutually exclusive
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&ucam_out0>;
                  // csi2 dphy lane number
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // csi2 host port name
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  // csi2 dphy port name
                  remote-endpoint = <&csidphy0_out>;
                  // csi2 host lane number
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  // Port name on the vicap side
                  remote-endpoint = <&cif_mipi_in>;
                  // csi2 host lane number
                  data-lanes = <1 2 3 4>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          /* MIPI CSI-2 endpoint */
          cif_mipi_in: endpoint {
              // csi2 hostport name
              remote-endpoint = <&mipi_csi2_output>;
              // vicap lane number
              data-lanes = <1 2 3 4>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          /* sditf endpoint */
          mipi_lvds_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //mipi csi2 dphy lane number, consistent with sensor
              data-lanes = <1 2 3 4>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //Endpoint name of vicap sditf
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };

RK356X platform

Take gc5025 2lane linking lane2/lane3 of rk3566 evb2 mipi csi2 dphy as an example:

Link relationship: sensor->csi2 dphy->mipi csi host->vicap Configuration points

data-lanes must specify the number of lanes used, otherwise it will not be recognized as mipi type;

dphy needs to be linked to the csi host node;

Need to enable csi2 dphy hw node.

  /* split mode: lane:2/3 */
  gc5025: gc5025@37 {
          status = "okay";
          // Need to be consistent with the matching string in the driver
          compatible = "galaxycore,gc5025";
          // sensor I2C device address, 7 bits
          reg = <0x37>;
          // sensor mclkSource configuration
          clocks = <&pmucru CLK_WIFI>;
          clock-names = "xvclk";
          //sensor mclk pinctlset up
          pinctrl-names = "default";
          pinctrl-0 = <&refclk_pins>;
          // resetPin assignment and effective level
          reset-gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
          //sensor Related power domain enable
          power-domains = <&power RK3568_PD_VI>;
          /*power-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;*/
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "front";
          // module name
          rockchip,camera-module-name = "TongJu";
          // lens name
          rockchip,camera-module-lens-name = "CHT842-MD";
          port {
              gc5025_out: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&dphy2_in>;
                  // csi2 dphy lane name,2lane is <1 2>, 4lane is <1 2 3 4>
                  data-lanes = <1 2>;
              };
          };
  };
   &csi2_dphy_hw {
          status = "okay";
   };
  &csi2_dphy2 {
      //csi2_dphy0 is not used simultaneously with csi2_dphy1/csi2_dphy2, mutually
  exclusivee;can be used in parallel with csi2_dphy1
      status = "okay";
      /*
       * dphy2 only used for split mode,
       * can be used  concurrently  with dphy1
       * full mode and split mode are mutually exclusive
       */
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&gc5025_out>;
                  // csi2 dphy lane name
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  // csi2 host port name
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  // csi2 dphy port name
                  remote-endpoint = <&dphy2_out>;
                  // csi2 host lane number
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  // vicapport name
                  remote-endpoint = <&cif_mipi_in>;
                  // csi2 host lane number
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              // csi2 hostport name
              remote-endpoint = <&mipi_csi2_output>;
              // vicap lane number
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          /* MIPI CSI-2 endpoint */
          mipi_lvds_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //mipi csi2 dphy lane number,consistent with sensor
              data-lanes = <1 2>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //vicap mipi sditf port name
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };
10.1.1.2 LVDS interface

RV1126/RV1109 platform

Take imx327 4lane as an example, the link relationship is as follows:

Link relationship: sensor->csi dphy->vicap Configuration points

dphy does not need to link to the CSI host node, otherwise it will cause no data to be received;

data-lanes must specify the specific number of lanes used, otherwise it will cause no data to be received;

The bus-type must be configured to 3, otherwise it will not be recognized as an LVDS interface, resulting in link establishment failure;

  imx327: imx327@1a {
          // Need to be consistent with the matching string in the driver
          compatible = "sony,imx327";
          // sensor I2C device address, 7 bits
          reg = <0x1a>;
          // sensor mclkSource configuration
          clocks = <&cru CLK_MIPICSI_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          power-domains = <&power RV1126_PD_VI>;
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          //sensor mclk pinctlset up
          pinctrl-names = "default";
          pinctrl-0 = <&mipicsi_clk0>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
          // resetPin assignment and effective level
          reset-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "front";
          // module name
          rockchip,camera-module-name = "CMK-OT1607-FV1";
          // lens name
          rockchip,camera-module-lens-name = "M12-4IR-4MP-F16";
          // ircut name
          ir-cut = <&cam_ircut0>;
          port {
              ucam_out0: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&mipi_in_ucam0>;
                  // lvds lane number,1lane is <1>, 4lane is <4>,must be specified
                  data-lanes = <4>;
                  // Type of lvds interface, must be specified
                  bus-type = <3>;
              };
          };
  };
  &csi_dphy0 {
      //csi2_dphy0 is not simultaneous use with csi2_dphy1/csi2_dphy2, mutually exclusive
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&ucam_out0>;
                  // lvds lane number,1lane is <1>, 4lane is <4>,must be specified
                  data-lanes = <4>;
                  // Type of lvds interface, must be specified
                  bus-type = <3>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // vicap liteport name
                  remote-endpoint = <&cif_lite_lvds_in>;
                  // lvds lane number,1lane is <1>, 4lane is <4>,must be specified
                  data-lanes = <4>;
                  // Type of lvds interface, must be specified
                  bus-type = <3>;
              };
          };
      };
  };
  &rkcif_lite_mipi_lvds {
      status = "okay";
      port {
          /* lvds endpoint */
          cif_lite_lvds_in: endpoint {
              // csi2 dphy port name
              remote-endpoint = <&csidphy0_out>;
              //csi2 dphy lvds lane name,1lane is <1>, 4lane is <4>,must be specified
              data-lanes = <4>;
              //Type of lvds interface, must be specified
              bus-type = <3>;
          };
      };
  };
  &rkcif_lite_sditf {
      status = "okay";
      port {
          /* lvds endpoint */
          lite_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //csi2 dphy lane number, consistent with sensor
              data-lanes = <4>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //lite vicap lvds sditf port name
                  remote-endpoint = <&lite_sditf>;
              };
          };
      };
  };
10.1.1.3 DVP interface

On the RV1126/RV1106/RK356X platform, the dts configuration of each related interface of DVP is the same.

BT601

Take ar0230 BT601 as an example, the link relationship is as follows:

Link relationship: sensor->vicap Configuration points

hsync-active/vsync-active must be configured for asynchronous registration of the v4l2 framework to identify the BT601 interface, if not configured, it will be identified as the BT656 interface;

pclk-sample/bus-width is optional;

In the g_mbus_config interface of the sensor driver, the valid polarity of the hsync-acitve/vsync-active/pclk- ative of the current sensor must be indicated by the flag, otherwise the data will not be received;

pinctrl needs to be quoted in order to do corresponding iomux for BT601 related gpio, otherwise it will lead to failure to receive data;

The sample code of the g_mbus_config interface is as follows:

  static int ar0230_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)
  {
      config->type = V4L2_MBUS_PARALLEL;
      config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
              V4L2_MBUS_VSYNC_ACTIVE_HIGH |
              V4L2_MBUS_PCLK_SAMPLE_FALLING;
      return 0;
  }

The DTS configuration example is as follows:

  ar0230: ar0230@10 {
          // Need to be consistent with the matching string in the driver
          compatible = "aptina,ar0230";
          // sensor I2C device address, 7 bits
          reg = <0x10>;
          // sensor mclkSource configuration
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          power-domains = <&power RV1126_PD_VI>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
          /*reset-gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;*/
          //Configure dvp related data pins and clock pins
          pinctrl-names = "default";
          pinctrl-0 = <&cifm0_dvp_ctl>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <0>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "back";
          // module name
          rockchip,camera-module-name = "CMK-OT0836-PT2";
          // lens name
          rockchip,camera-module-lens-name = "YT-2929";
          port {
              cam_para_out1: endpoint {
                  remote-endpoint = <&cif_para_in>;
              };
          };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          /* Parallel bus endpoint */
          cif_para_in: endpoint {
              //sensor port endpoint name
              remote-endpoint = <&cam_para_out1>;
              //Sensor configuration parameters
              bus-width = <12>;
              hsync-active = <1>;
              vsync-active = <1>;
              pclk-sample = <0>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      port {
          /* parallel endpoint */
          dvp_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //Sensor configuration parameters
              bus-width = <12>;
              hsync-active = <1>;
              vsync-active = <1>;
              pclk-sample = <0>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //dvp sditf port name
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };

BT656/BT1120

The dts usage of BT656/BT1120 is the same.

Take ava fpga bt1120 as an example, the link relationship is as follows:

Link relationship: sensor->vicap Configuration points

Do not configure hsync-active/vsync-active, otherwise the v4l2 framework will recognize it as BT601 during asynchronous registration;

pclk-sample/bus-width is optional;

In the g_mbus_config interface of the sensor driver, the valid polarity of the pclk-ative of the current sensor must be indicated by the flag, otherwise the data will not be received;

The querystd interface in v4l2_subdev_video_ops must be implemented, indicating that the current interface is an ATSC interface, otherwise the data will not be received;

pinctrl needs to be quoted in order to do corresponding iomux for bt656/bt1120 related gpio, otherwise it will result in failure to receive data.

The sample code of the g_mbus_config interface is as follows:

  static int avafpga_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)
  {
      config->type = V4L2_MBUS_BT656;
      config->flags = V4L2_MBUS_PCLK_SAMPLE_RISING;
      return 0;
  }

An example of the querystd interface is as follows:

  static int avafpga_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
  {
      *std = V4L2_STD_ATSC;
      return 0;
  }

The dts configuration example is as follows:

  avafpga: avafpga@70 {
      // Need to be consistent with the matching string in the driver
      compatible = "ava,fpga";
      // sensor I2C device address, 7 bits
      reg = <0x10>;
      // sensor mclkSource configuration
      clocks = <&cru CLK_CIF_OUT>;
      clock-names = "xvclk";
      //sensor Related power domain enable
      avdd-supply = <&vcc_avdd>;
      dovdd-supply = <&vcc_dovdd>;
      dvdd-supply = <&vcc_dvdd>;
      // powerdownPin assignment and effective level
      power-domains = <&power RV1126_PD_VI>;
      pwdn-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
      /*reset-gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;*/
      //Configure dvp related data pins and clock pins
      pinctrl-names = "default";
      pinctrl-0 = <&cifm0_dvp_ctl>;
      // Module number, this number should not be repeated
      rockchip,camera-module-index = <0>;
      // Module orientation, there are "back" and "front"
      rockchip,camera-module-facing = "back";
      // module name
      rockchip,camera-module-name = "CMK-OT0836-PT2";
      // lens name
      rockchip,camera-module-lens-name = "YT-2929";
      port {
          cam_para_out2: endpoint {
              remote-endpoint = <&cif_para_in>;
          };
      };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          /* Parallel bus endpoint */
          cif_para_in: endpoint {
              //sensor port endpoint name
              remote-endpoint = <&cam_para_out2>;
              //Sensor configuration parameters,Optional
              bus-width = <16>;
              pclk-sample = <1>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      port {
          /* parallel endpoint */
          dvp_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              bus-width = <16>;
              pclk-sample = <1>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //dvp sditf port name
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };

10.1.2 Multi-sensor registration

A single hardware isp virtualizes multiple devices and processes multiple raw sensor data in time division multiplexing.

For rv1109/rv1126/rk356x vicap to collect dvp raw data can only be stored in non-compact storage, ISP processing raw by default is stored in compact storage, for the precautions of dvp raw data processing in isp, please refer to How to configure ISP/VICAP RAW storage format.

10.1.3 RV1126/RV1109

Link relationship, isp0->ispp0 and isp1->ispp1 are fixed configuration RV1126.dtsi

rv1109/rv1126 isp/ispp, up to 4 channels can be multiplexed if the bandwidth allows, you can add rkisp_vir0~rkisp_vir4/rkispp_vir0~rkispp_vir4 to rv1126.dtsi by yourself.

Mipi into isp or cif into isp is optional.

rv1109/rv1126 supports 2 phy interfaces, each phy can be reused as mipi/lvds, and supports up to 4 lanes rv1109/rv1126 supports 1 dvp interface, supports BT601/BT656/BT1120 ISP: supports mipi or dvp input, mipi/dvp cannot work at the same time Vicap: supports mipi/lvds/dvp, mipi/lvds is multiplexed, cannot be used at the same time, dvp can be used at the same time as the former. vicap lite: only supports lvds Through the understanding of the above hardware configuration, rv1109/rv1126 currently supports up to 3 raw sensors into the isp processing

10.1.3.1 Double camera into isp processing

sensor0(mipi)->csi_dphy0->csi2->vicap->isp0->ispp0 sensor1(mipi)->csi_dphy1->isp1->ispp1

Example reference arch/arm/boot/dts/RV1109-evb-ddr3-v12-facial-gate.dts gc2053->csi_dphy0->csi2->cif->isp1->ispp1 ov2718->csi_dphy1->isp0->ispp0 The following configuration is very important for different resolutions

&rkispp {
     status = "okay";
     /* the max input w h and fps of mulit sensor */
     max-input = <2688 1520 30>;//Take the maximum width and height and frame rate of different sensors
};
10.1.3.2 Three camera into isp processing

sensor0(mipi)->csi_dphy0->csi2->vicap->isp0->ispp0 sensor1(mipi)->csi_dphy1->isp1->ispp1 sensor2(DVP)->vicap->isp2->ispp2

or

sensor0(mipi)->csi_dphy0->csi2->vicap->isp0->ispp0 sensor1(lvds)->csi_dphy1->vicap lite->isp1->ispp1 sensor2(DVP)->vicap->isp2->ispp2

E.g: bf2253-0(mipi)->dphy0->csi2->vicap(mipi)->isp0->ispp0 bf2253-1(mipi)->dphy1->isp1->ispp1 gc1054(dvp)->vicap(dvp)->isp2->ispp2

  &i2c1 {
      status = "okay";
      clock-frequency = <400000>;
      gc1054: gc1054@21 {
              compatible = "galaxycore,gc1054";
              reg = <0x21>;
              clocks = <&cru CLK_CIF_OUT>;
              clock-names = "xvclk";
              power-domains = <&power RV1126_PD_VI>;
              pwdn-gpios  = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>;
              reset-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
              rockchip,grf = <&grf>;
              pinctrl-names = "default";
              pinctrl-0 = <&cifm0_dvp_ctl>;
              rockchip,camera-module-index = <0>;
              rockchip,camera-module-facing = "back";
              rockchip,camera-module-name = "GC1054_B";
              rockchip,camera-module-lens-name = "GC1054_LEN";
              port {
                      cam_para_out1: endpoint {
                      remote-endpoint = <&cif_para_in>;
                          bus-width = <10>;
                          hsync-active = <1>;
                          vsync-active = <1>;
              };
          };
      };
      bf2253_isp0: bf2253_isp0@6d {
            compatible = "ovti,bf2253_isp0";
            reg = <0x6d>;
            clocks = <&cru CLK_MIPICSI_OUT>;
            clock-names = "xvclk";
            power-domains = <&power RV1126_PD_VI>;
            pinctrl-names = "rockchip,camera_default";
            pinctrl-0   = <&mipicsi_clk0>;
            power-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
            pwdn-gpios  = <&gpio1 RK_PD4 GPIO_ACTIVE_LOW>;
            reset-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
            avdd-supply  = <&vcc_3v3>;
            dovdd-supply = <&vcc_1v8>;
            dvdd-supply  = <&vcc_1v8>;
            rockchip,camera-module-index = <1>;
            rockchip,camera-module-facing = "front";
            rockchip,camera-module-name = "LA6110PA";
            rockchip,camera-module-lens-name = "YM6011P";
            port {
                cam_out1: endpoint {
                      remote-endpoint = <&mipi_in_ucam>;
                      data-lanes = <1>;
                  };
            };
       };
  };
  &i2c3 {
      status = "okay";
      clock-frequency = <400000>;
      pinctrl-names = "default";
      pinctrl-0 = <&i2c3m2_xfer>;
      bf2253_isp1: bf2253_isp1@6d {
            compatible = "ovti,bf2253_isp1";
            reg = <0x6d>;
            clocks = <&cru CLK_MIPICSI_OUT>;
            clock-names = "xvclk";
            power-domains = <&power RV1126_PD_VI>;
            pinctrl-names = "rockchip,camera_default";
            //pinctrl-names = "rockchip,camera_sleep";
            pinctrl-0 = <&mipicsi_clk1>;
            power-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
            pwdn-gpios  = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>;
            reset-gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>;
            avdd-supply  = <&vcc_3v3>;
            dovdd-supply = <&vcc_1v8>;
            dvdd-supply  = <&vcc_1v8>;
            rockchip,camera-module-index = <2>;
            rockchip,camera-module-facing = "front";
            rockchip,camera-module-name = "LA6110PA";
            rockchip,camera-module-lens-name = "YM6011P";
            port {
                 cam_out0: endpoint {
                     remote-endpoint = <&csi_dphy1_input>;
                     data-lanes = <1>;
                 };
            };
       };
  };
  &csi_dphy0 {
      status = "okay";
      ports {
          port@0 {
              mipi_in_ucam: endpoint@1 {
                  remote-endpoint = <&cam_out1>;
                  data-lanes = <1>;
              };
          };
          port@1 {
              csi_dphy0_out: endpoint@0 {
                  remote-endpoint = <&mipi_csi2_input>;
                  data-lanes = <1>;
              };
          };
      };
  };
  &csi_dphy1 {
      status = "okay";
      ports {
          port@0 {
              csi_dphy1_input: endpoint@1 {
                  remote-endpoint = <&cam_out0>;
                  data-lanes = <1>;
              };
          };
          port@1 {
              csi_dphy1_output: endpoint@0 {
                  remote-endpoint = <&isp_in1>;
                  data-lanes = <1>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          port@0 {
              mipi_csi2_input: endpoint@1 {
                  remote-endpoint = <&csi_dphy0_out>;
                  data-lanes = <1>;
              };
          };
          port@1 {
              mipi_csi2_output: endpoint@0 {
                  remote-endpoint = <&cif_mipi_in>;
                  data-lanes = <1>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          lvds_sditf: endpoint {
              remote-endpoint = <&isp_in0>;
              data-lanes = <1>;
          };
      };
  };
  &rkcif_dvp {
          status = "okay";
          //iommus = <&rkcif_mmu>;
          ///delete-property/ memory-region;
          port {
                  /* Parallel bus endpoint */
                  cif_para_in: endpoint {
                          remote-endpoint = <&cam_para_out1>;
                          bus-width = <8>;
                          hsync-active = <1>;
                          vsync-active = <1>;
                  };
          };
  };
  &rkcif_dvp_sditf {
          status = "okay";
          port {
                  /* Parallel bus endpoint */
          dvp_sditf: endpoint {
                          remote-endpoint = <&isp_in2>;
                  };
          };
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in0: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&lvds_sditf>;
              };
          };
      };
  };
  &rkisp_vir1 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in1: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&csi_dphy1_output>;
              };
          };
      };
  };
  &rkisp_vir2 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in2: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };
  &rkispp_vir0 {
      status = "okay";
  };
  &rkispp_vir1 {
      status = "okay";
  };
  &rkispp_vir2 {
          status = "okay";
  };
  &rkcif {
          status = "okay";
  };
  rkisp: rkisp@ffb50000 {
      status = "okay";
  };
  &rkispp {
      status = "okay";
      max-input = <1600 1200 30>;
      memory-region = <&isp_reserved>;
      /* the max input w h and fps of mulit sensor */
  };
   rkcif_mmu: iommu@ffae0800{
      status = "disabled";
  };
   rkisp_mmu: iommu@ffb51a00 {
      status = "disabled";
  };
  &rkispp_mmu {
      status = "disabled";
  };

10.1.4 RK3566/RK3568

rk356x isp, up to 4 channels can be multiplexed if the bandwidth allows, you can add rkisp_vir0~rkisp_vir4 in rk3568.dtsi by yourself.

Mipi into isp or cif into isp is optional.

rk356x supports 1 4lane phy interface, this phy can be divided into 2 2lane phy rk356x supports 1 dvp interface, supports BT601/BT656/BT1120 ISP supports mipi or dvp input: mipi/dvp can only choose 1 from 2 and cannot work at the same time vicap supports mipi/dvp: mipi and dvp can be used at the same time Through the understanding of the above hardware configuration, rk356x currently supports up to 3 raw sensors to enter isp processing

10.1.4.1 Double camera into isp processing:

E.g:

ov5695->dphy1->isp_vir0

gc5025->dphy2->csi2->vicap->isp_vir1

  ov5695: ov5695@36 {
          status = "okay";
          ...
          port {
              ov5695_out: endpoint {
                  remote-endpoint = <&dphy1_in>;
                  data-lanes = <1 2>;
              };
          };
  };
  gc5025: gc5025@37 {
          status = "okay";
          ...
          port {
              gc5025_out: endpoint {
                  remote-endpoint = <&dphy2_in>;
                  data-lanes = <1 2>;
              };
          };
  };
   &csi2_dphy_hw {
          status = "okay";
   };
  &csi2_dphy1 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&ov5695_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&isp0_in>;
              };
          };
      };
  };
  &csi2_dphy2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&gc5025_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&dphy2_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&cif_mipi_in>;
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          mipi_lvds_sditf: endpoint {
              remote-endpoint = <&isp1_in>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkisp {
      status = "okay";
      /* the max input w h and fps of mulit sensor */
      max-input = <2592 1944 30>;
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp0_in: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&dphy1_out>;
              };
          };
      };
  };
  &rkisp_vir1 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp1_in: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };
10.1.4.2 Three camera into isp processing

E.g: gc2053(mipi)->dphy1->isp0 sc1330(dvp)->vicap(dvp)->isp1 ov5695(mipi)->dphy2->csi2->vicap(mipi)->isp2

  &i2c2 {
      status = "okay";
      pinctrl-0 = <&i2c2m1_xfer>;
      /* split mode: lane0/1 */
      gc2053: gc2053@37 {
          status = "okay";
          compatible = "galaxycore,gc2053";
          reg = <0x37>;
          clocks = <&cru CLK_CAM0_OUT>;
          clock-names = "xvclk";
          /* Set pinctl of xvclk in &pinctl */
          power-domains = <&power RK3568_PD_VI>;
          reset-gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_LOW>;
          pwdn-gpios = <&gpio3 RK_PD0 GPIO_ACTIVE_LOW>;
          /*power-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;*/
          rockchip,camera-module-index = <0>;
          rockchip,camera-module-facing = "front";
          rockchip,camera-module-name = "rgbd";
          rockchip,camera-module-lens-name = "Optics";
          port {
              gc2053_out: endpoint {
                  remote-endpoint = <&dphy1_in>;
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &i2c3 {
      status = "okay";
      pinctrl-0 = <&i2c3m0_xfer>;
      sc1330: sc1330@32 {
          status = "okay";
          compatible = "smartsens,sc1330";
          reg = <0x32>;
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          power-domains = <&power RK3568_PD_VI>;
          pinctrl-names = "default";
          /* conflict with gmac1m1_rgmii_pins & cif_clk*/
          pinctrl-0 = <&cif_clk &cif_dvp_clk &cif_dvp_bus10>;
          /*avdd-supply = <&vcc2v8_dvp>;*/
          /*dovdd-supply = <&vcc1v8_dvp>;*/
          /*dvdd-supply = <&vcc1v8_dvp>;*/
          reset-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_LOW>;
          pwdn-gpios = <&gpio3 RK_PC7 GPIO_ACTIVE_LOW>;
          rockchip,camera-module-index = <2>;
          rockchip,camera-module-facing = "back";
          rockchip,camera-module-name = "default";
          rockchip,camera-module-lens-name = "default";
          port {
              sc1330_out: endpoint {
                  remote-endpoint = <&dvp_in_bcam>;
              };
          };
      };
  };
  &i2c4 {
      status = "okay";
      pinctrl-0 = <&i2c4m0_xfer>;
      clock-frequency = <1000000>;
      /* split mode: lane:2/3 */
      ov5695: ov5695@36 {
                  status = "okay";
                  compatible = "ovti,ov5695";
                  reg = <0x36>;
                  clocks = <&cru CLK_CAM0_OUT>;
                  clock-names = "xvclk";
                  power-domains = <&power RK3568_PD_VI>;
                  pinctrl-names = "default";
                  pinctrl-0 = <&cif_clk>;
                  reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
                  pwdn-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
                  rockchip,camera-module-index = <1>;
                  rockchip,camera-module-facing = "front";
                  rockchip,camera-module-name = "TongJu";
                  rockchip,camera-module-lens-name = "CHT842-MD";
                  port {
                          ov5695_out: endpoint {
                                  remote-endpoint = <&dphy2_in>;
                                  data-lanes = <1 2>;
                          };
                  };
      };
  };
  &csi2_dphy_hw {
      status = "okay";
  };
  &csi2_dphy1 {
      status = "okay";
      /*
       * dphy1 only used for split mode,
       * can be used  concurrently  with dphy2
       * full mode and split mode are mutually exclusive
       */
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&gc2053_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&isp0_in>;
              };
          };
      };
  };
  &csi2_dphy2 {
      status = "okay";
      /*
       * dphy2 only used for split mode,
       * can be used  concurrently  with dphy1
       * full mode and split mode are mutually exclusive
       */
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&ov5695_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&dphy2_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&cif_mipi_in>;
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif {
      status = "okay";
  };
  &rkcif_mmu {
      status = "okay";
  };
  &rkcif_mipi_lvds {
      status = "okay";
      /* csi2 link to rkcif, using rkcif to capture stream */
      port {
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          mipi_lvds_sditf: endpoint {
              remote-endpoint = <&isp2_in>;
          };
      };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          dvp_in_bcam: endpoint {
              remote-endpoint = <&sc1330_out>;
              bus-width = <10>;
              vsync-active = <0>;
              hsync-active = <1>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      /* parallel endpoint */
      port {
          dvp_sditf: endpoint {
              remote-endpoint = <&isp1_in>;
              bus-width = <10>;
              pclk-sample = <1>;
          };
      };
  };
  &rkisp {
      status = "okay";
      /* the max input w h and fps of mulit sensor */
      max-input = <1920 1080 30>;
  };
  &rkisp_mmu {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp0_in: endpoint@0 {
              reg = <0>;
              remote-endpoint = <&dphy1_out>;
          };
      };
  };
  &rkisp_vir1 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp1_in: endpoint@0 {
              reg = <0>;
              remote-endpoint = <&dvp_sditf>;
          };
      };
  };
  &rkisp_vir2 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp2_in: endpoint@0 {
              reg = <0>;
              remote-endpoint = <&mipi_lvds_sditf>;
          };
      };
  };

10.2 CIS driver description

Camera Sensor uses I2C to interact with the host. The sensor driver is currently implemented in accordance with the I2C device driver. The sensor driver also uses the v4l2 subdev method to interact with the host driver.

10.2.1 Brief description of data type

10.2.1.1 struct i2c_driver

[Description]

Define i2c device driver information

[Definition]

  struct i2c_driver {
      ……
      /* Standard driver model interfaces */
      int (*probe)(struct i2c_client *, const struct i2c_device_id *);
      int (*remove)(struct i2c_client *);
      ……
      struct device_driver driver;
      const struct i2c_device_id *id_table;
      ……
  };

[Key Member]

Member name Description
@driver Device driver model driver mainly contains the name of the driver and the of_match_table that matches the DTS registered device. When the compatible field in of_match_table matches the compatible field in the dts file, the .probe function will be called
@id_table List of I2C devices supported by this driver If the kernel does not use of_match_table and dts registered devices for matching, the kernel uses this table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  #if IS_ENABLED(CONFIG_OF)
  static const struct of_device_id os04a10_of_match[] = {
      { .compatible = "ovti,os04a10" },
      {},
  };
  MODULE_DEVICE_TABLE(of, os04a10_of_match);
  #endif
  static const struct i2c_device_id os04a10_match_id[] = {
      { "ovti,os04a10", 0 },
      { },
  };
  static struct i2c_driver os04a10_i2c_driver = {
      .driver = {
          .name = OS04A10_NAME,
          .pm = &os04a10_pm_ops,
          .of_match_table = of_match_ptr(os04a10_of_match),
      },
      .probe      = &os04a10_probe,
      .remove     = &os04a10_remove,
      .id_table   = os04a10_match_id,
  };
  static int __init sensor_mod_init(void)
  {
      return i2c_add_driver(&os04a10_i2c_driver);
  }
  static void __exit sensor_mod_exit(void)
  {
      i2c_del_driver(&os04a10_i2c_driver);
  }
  device_initcall_sync(sensor_mod_init);
  module_exit(sensor_mod_exit);
10.2.1.2 struct v4l2_subdev_ops

[Description]

Define ops callbacks for subdevs.

[definition]

  struct v4l2_subdev_ops {
      const struct v4l2_subdev_core_ops   *core;
      ……
      const struct v4l2_subdev_video_ops  *video;
      ……
      const struct v4l2_subdev_pad_ops    *pad;
  };

[Key Member]

Member name Description
.core Define core ops callbacks for subdevs
.video Callbacks used when v4l device was opened in video mode.
.pad v4l2-subdev pad level operations

[Example]

  static const struct v4l2_subdev_ops os04a10_subdev_ops = {
      .core   = &os04a10_core_ops,
      .video  = &os04a10_video_ops,
      .pad    = &os04a10_pad_ops,
  };
10.2.1.3 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      int (*s_power)(struct v4l2_subdev *sd, int on);
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
          unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name Description
.s_power puts subdevice in power saving mode (on == 0) or normal operation mode (on == 1).
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops os04a10_core_ops = {
      .s_power = os04a10_s_power,
      .ioctl = os04a10_ioctl,
  #ifdef CONFIG_COMPAT
      .compat_ioctl32 = os04a10_compat_ioctl32,
  #endif
  };

At present, the following private ioctl is used to realize the query of module information and the query setting of OTP information

Private ioctl description
RKMODULE_GET_MODULE_INFO Get module information, refer to struct rkmodule_inf;
RKMODULE_AWB_CFG Switch sensor’s compensation function for AWB; if the module does not burn the golden AWB value, you can set it here; for details, please refer to struct rkmodule awb_cfg;
RKMODULE_LSC_CFG Switch sensor’s compensation function for LSC; refer to struct rkmodule_lsc_cfg;
PREISP_CMD_SET_HDRAE_EXP HDR exposure setting detailed reference struct preisp_hdrae_exp_s
RKMODULE_SET_HDR_CFG Set the HDR mode to switch between normal and HDR modes. Need to drive to adapt to normal and HDR 2 groups of configuration information, please refer to struct rkmodule_hdr_cfg for details
RKMODULE_GET_HDR_CFG To get the current HDR mode, please refer to struct rkmodule_hdr_cfg for details
RKMODULE_SET_CONVERSION_GAIN Set the conversion gain of linear mode, such as imx347, os04a10 sensor with conversion gain function, if the sensor does not support conversion gain, it may not be implemented
10.2.1.4 struct v4l2_subdev_video_ops

[Description]

Callbacks used when v4l device was opened in video mode.

[Definition]

  struct v4l2_subdev_video_ops {
      ……
      int (*s_stream)(struct v4l2_subdev *sd, int enable);
      ……
      int (*g_frame_interval)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_frame_interval *interval);
      int (*g_mbus_config)(struct v4l2_subdev *sd,
                 struct v4l2_mbus_config *cfg);
   ……
  };

[Key Member]

Member name Description
.g_frame_interval callback for VIDIOC_SUBDEV_G_FRAME_INTERVAL ioctl handler code
.s_stream used to notify the driver that a video stream will start or has stopped
.g_mbus_config get supported mediabus configurations

[Example]

  static const struct v4l2_subdev_video_ops os04a10_video_ops = {
      .s_stream = os04a10_s_stream,
      .g_frame_interval = os04a10_g_frame_interval,
      .g_mbus_config = os04a10_g_mbus_config,
  };
10.2.1.5 struct v4l2_subdev_pad_ops

[Description]

v4l2-subdev pad level operations

[Definition]

  struct v4l2_subdev_pad_ops {
      ……
      int (*enum_mbus_code)(struct v4l2_subdev *sd,
                 struct v4l2_subdev_pad_config *cfg,
                 struct v4l2_subdev_mbus_code_enum *code);
      int (*enum_frame_size)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_frame_size_enum *fse);
      int (*get_fmt)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_format *format);
      int (*set_fmt)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_format *format);
      int (*enum_frame_interval)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_frame_interval_enum *fie);
      int (*get_selection)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_selection *sel);
      ……
  };

[Key Member]

Member name Description
. enum_mbus_code callback for VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl handler code.
. enum_frame_size callback for VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl handler code.
.s_fmt callback for VIDIOC_SUBDEV_S_FMT ioctl handler code.
.g_fmt callback for VIDIOC_SUBDEV_G_FMT ioctl handler code
.enum_frame_interval callback for VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL() ioctl handler code.
.get_selection callback for VIDIOC_SUBDEV_G_SELECTION() ioctl handler code.

[Example]

  static const struct v4l2_subdev_pad_ops os04a10_pad_ops = {
      .enum_mbus_code = os04a10_enum_mbus_code,
      .enum_frame_size = os04a10_enum_frame_sizes,
      .enum_frame_interval = os04a10_enum_frame_interval,
      .get_fmt = os04a10_get_fmt,
      .set_fmt = os04a10_set_fmt,
  };
10.2.1.6 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name Description
.s_ctrl actually set the new control value.

[Example]

  static const struct v4l2_ctrl_ops os04a10_ctrl_ops = {
      .s_ctrl = os04a10_set_ctrl,
  };

The RKISP driver requires the use of user controls provided by the framework. The cameras sensor driver must implement the following control functions, refer to CIS driver V4L2-controls list 1

10.2.1.7 struct xxxx_mode

[Description]

Sensor can support the information of each mode.

This structure can often be seen in the sensor driver, although it is not required by the v4l2 standard.

[Definition]

  struct xxxx_mode {
      u32 bus_fmt;
      u32 width;
      u32 height;
      struct v4l2_fract max_fps;
      u32 hts_def;
      u32 vts_def;
      u32 exp_def;
      const struct regval *reg_list;
      u32 hdr_mode;
      u32 vc[PAD_MAX];
  };

[Key Member]

Member name Description
.bus_fmt Sensor output format, reference MEDIA_BUS_FMT table
.width The effective image width, which needs to be consistent with the width output of the sensor currently configured
.height The effective image height, which needs to be consistent with the height output of the sensor currently configured
.max_fps Image FPS, denominator/numerator is fps
hts_def Default HTS, which is the effective image width + HBLANK
vts_def Default VTS, which is the effective image height + VBLANK
exp_def Default exposure time
*reg_list Register list
.hdr_mode Sensor working mode, support linear mode, two-frame synthesis HDR, three-frame synthesis HDR
.vc[PAD_MAX] Configure MIPI VC channel

[Example]

   enum os04a10_max_pad {
      PAD0, /* link to isp */
      PAD1, /* link to csi rawwr0 | hdr x2:L x3:M */
      PAD2, /* link to csi rawwr1 | hdr    x3:L */
      PAD3, /* link to csi rawwr2 | hdr x2:M x3:S */
      PAD_MAX,
  };
  static const struct os04a10_mode supported_modes[] = {
      {
          .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
          .width = 2688,
          .height = 1520,
          .max_fps = {
              .numerator = 10000,
              .denominator = 300372,
          },
          .exp_def = 0x0240,
          .hts_def = 0x05c4 * 2,
          .vts_def = 0x0984,
          .reg_list = os04a10_linear12bit_2688x1520_regs,
          .hdr_mode = NO_HDR,
          .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
      }, {
          .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
          .width = 2688,
          .height = 1520,
          .max_fps = {
              .numerator = 10000,
              .denominator = 225000,
          },
          .exp_def = 0x0240,
          .hts_def = 0x05c4 * 2,
          .vts_def = 0x0658,
          .reg_list = os04a10_hdr12bit_2688x1520_regs,
          .hdr_mode = HDR_X2,
          .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
          .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
          .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
          .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
      },
  };
10.2.1.8 struct v4l2_mbus_framefmt

[Description]

frame format on the media bus

[Definition]

  struct v4l2_mbus_framefmt {
      __u32           width;
      __u32           height;
      __u32           code;
      __u32           field;
      __u32           colorspace;
      __u16           ycbcr_enc;
      __u16           quantization;
      __u16           xfer_func;
      __u16           reserved[11];
  };

[Key Member]

Member name Description
width Frame width
height Frame height
code Reference to MEDIA_BUS_FMT table
field V4L2_FIELD_NONE: Frame output mode V4L2_FIELD_INTERLACED: Field output mode

[Example]

10.2.1.9 struct rkmodule_base_inf

[Description]

Basic module information, the upper layer uses this information to match with IQ

[Definition]

  struct rkmodule_base_inf {
      char sensor[RKMODULE_NAME_LEN];
      char module[RKMODULE_NAME_LEN];
      char lens[RKMODULE_NAME_LEN];
  } __attribute__ ((packed));

[Key Member]

Member name Description
sensor sensor name, obtained from the sensor driver
module module name, obtained from DTS configuration, subject to module data
lens Lens name, obtained from DTS configuration, subject to module data

[Example]

10.2.1.10 struct rkmodule_fac_inf

[Description]

Module OTP factory information

[Definition]

  struct rkmodule_fac_inf {
      __u32 flag;
      char module[RKMODULE_NAME_LEN];
      char lens[RKMODULE_NAME_LEN];
      __u32 year;
      __u32 month;
      __u32 day;
  } __attribute__ ((packed));

[Key Member]

Member name Description
flag Whether the group information is valid or not
module module name, get the number from OTP, get the module name from the number
lens Lens name, get the number from OTP, get the lens name from the number
year Year of production, such as 12 for 2012
month Production month
day Production date

[Example]

10.2.1.11 struct rkmodule_awb_inf

[Description]

Module OTP awb measurement information

[Definition]

  struct rkmodule_awb_inf {
      __u32 flag;
      __u32 r_value;
      __u32 b_value;
      __u32 gr_value;
      __u32 gb_value;
      __u32 golden_r_value;
      __u32 golden_b_value;
      __u32 golden_gr_value;
      __u32 golden_gb_value;
  } __attribute__ ((packed));

[Key Member]

Member name Description
flag Whether the group information is valid or not
r_value AWB R measurement information of the current module
b_value AWB B measurement information of the current module
gr_value AWB GR measurement information of the current module
gb_value AWB GB measurement information of the current module
golden_r_value AWB R measurement information of a typical module, if not programmed, set to 0
golden_b_value AWB B measurement information of a typical module, if not programmed, set to 0
golden_gr_value AWB GR measurement information of a typical module, if not programmed, set to 0
golden_gb_value AWB GB measurement information of a typical module, if not programmed, set to 0

[Example]

10.2.1.12 struct rkmodule_lsc_inf

[Description]

Module OTP lsc measurement information

[Definition]

  struct rkmodule_lsc_inf {
      __u32 flag;
      __u16 lsc_w;
      __u16 lsc_h;
      __u16 decimal_bits;
      __u16 lsc_r[RKMODULE_LSCDATA_LEN];
      __u16 lsc_b[RKMODULE_LSCDATA_LEN];
      __u16 lsc_gr[RKMODULE_LSCDATA_LEN];
      __u16 lsc_gb[RKMODULE_LSCDATA_LEN];
  } __attribute__ ((packed));

[Key Member]

Member name Description
flag Whether the group information is valid or not
lsc_w The actual width of the lsc table
lsc_h lsc table actual height
decimal_bits The number of decimal places of the lsc measurement information, if it is not available, set it to 0
lsc_r lsc r measurement information
lsc_b lsc b measurement information
lsc_gr lsc gr measurement information
lsc_gb lsc gb measurement information

[Example]

10.2.1.13 struct rkmodule_af_inf

[Description]

Module OTP af measurement information

[Definition]

  struct rkmodule_af_inf {
      __u32 flag; // Whether this group of information is a valid flag
      __u32 vcm_start; // vcm start current
      __u32 vcm_end; // vcm termination current
      __u32 vcm_dir; // vcm measurement direction
  } __attribute__ ((packed));

[Key Member]

Member name Description
flag Whether the group information is valid or not
vcm_start vcm start current
vcm_end vcm end current
vcm_dir vcm determination direction

[Example]

10.2.1.14 struct rkmodule_inf

[Description]

Module information

[Definition]

  struct rkmodule_inf {
      struct rkmodule_base_inf base;
      struct rkmodule_fac_inf fac;
      struct rkmodule_awb_inf awb;
      struct rkmodule_lsc_inf lsc;
      struct rkmodule_af_inf af;
  } __attribute__ ((packed));

[Key Member]

Member name Description
base Module basic information
fac Module OTP Factory Information
awb Module OTP awb measurement information
lsc Module OTP lsc measurement information
af Module OTP af measurement information

[Example]

10.2.1.15 struct rkmodule_awb_cfg

[Description]

Module OTP awb configuration information

[Definition]

  struct rkmodule_awb_cfg {
      __u32 enable;
      __u32 golden_r_value;
      __u32 golden_b_value;
      __u32 golden_gr_value;
      __u32 golden_gb_value;
  } __attribute__ ((packed));

[Key Member]

Member name Description
enable Identifies whether awb correction is enabled
golden_r_value AWB R measurement information of a typical module
golden_b_value AWB B measurement information of a typical module
golden_gr_value AWB GR measurement information of a typical module
golden_gb_value AWB GB measurement information of a typical module

[Example]

10.2.1.16 struct rkmodule_lsc_cfg

[Description]

Module OTP lsc configuration information

[Definition]

  struct rkmodule_lsc_cfg {
      __u32 enable;
  } __attribute__ ((packed));

[Key Member]

Member name Description
enable Identifies whether lsc correction is enabled

[Example]

10.2.1.17 struct rkmodule_hdr_cfg

[Description]

hdr configuration information

[Definition]

  struct rkmodule_hdr_cfg {
      __u32 hdr_mode;
      struct rkmodule_hdr_esp esp;
  } __attribute__ ((packed));
  struct rkmodule_hdr_esp {
      enum hdr_esp_mode mode;
      union {
          struct {
              __u32 padnum;
              __u32 padpix;
          } lcnt;
          struct {
              __u32 efpix;
              __u32 obpix;
          } idcd;
      } val;
  };

[Key Member]

Member name Description
hdr_mode NO_HDR=0 //normal mode HDR_X2=5 //hdr 2 frame mode HDR_X3=6 //hdr 3 frame mode
struct rkmodule_hdr_esp hdr especial mode
enum hdr_esp_mode HDR_NORMAL_VC=0 //Normal virtual channel mode HDR_LINE_CNT=1 //Line counter mode (AR0239) HDR_ID_CODE=2 //Identification code mode(IMX327)

[Example]

10.2.1.18 struct preisp_hdrae_exp_s

[Description]

HDR exposure parameters

[Definition]

  struct preisp_hdrae_exp_s {
      unsigned int long_exp_reg;
      unsigned int long_gain_reg;
      unsigned int middle_exp_reg;
      unsigned int middle_gain_reg;
      unsigned int short_exp_reg;
      unsigned int short_gain_reg;
      unsigned int long_exp_val;
      unsigned int long_gain_val;
      unsigned int middle_exp_val;
      unsigned int middle_gain_val;
      unsigned int short_exp_val;
      unsigned int short_gain_val;
      unsigned char long_cg_mode;
      unsigned char middle_cg_mode;
      unsigned char short_cg_mode;
  };

[Key Member]

Member name Description
long_exp_reg Long frame exposure register value
long_gain_reg Long frame gain register value
middle_exp_reg Middle frame exposure register value
middle_gain_reg; Middle frame gain register value
short_exp_reg Short frame exposure register value
short_gain_reg Short frame gain register value
long_cg_mode Long frame conversion gain, 0 LCG, 1 HCG
middle_cg_mode middle frame conversion gain, 0 LCG, 1 HCG
short_cg_mode Short frame conversion gain, 0 LCG, 1 HCG

[Description]

In the preisp_hdrae_exp_s structure, you only need to pay attention to several parameters described by [key members]. The formula for converting exposure and gain values into registers is in iq xml. Please refer to the iq xml format description for specific conversion. The conversion gain requires the Sensor itself to support this function. If senosr not support conversion gain, you don’t need to pay attention to the conversion parameter, For HDR2X, you should set the passed mid-frame and short-frame parameters into the exposure parameter register corresponding to the two frames of the sensor output.

[Example]

10.2.2 API brief description

10.2.2.1 xxxx_set_fmt

[description]

Set the sensor output format.

[grammar]

  static int xxxx_set_fmt(struct v4l2_subdev *sd,
                          struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
*cfg subdev pad information structure pointer input
*fmt Pad-level media bus format structure pointer Input

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.2 xxxx_get_fmt

[description]

Get the sensor output format.

[grammar]

  static int xxxx_get_fmt(struct v4l2_subdev *sd,
                          struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
*cfg subdev pad information structure pointer input
*fmt Pad-level media bus format structure pointer Output

[return value]

Return value Description
0 Success
Not 0 Failed

reference to MEDIA_BUS_FMT table

10.2.2.3 xxxx_enum_mbus_code

[description]

Enumerate sensor output bus format.

[grammar]

  static int xxxx_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_mbus_code_enum *code)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
*cfg subdev pad information structure pointer input
*code media bus format enumeration structure pointer output

[return value]

Return value Description
0 Success
Not 0 Failed

The following table summarizes the corresponding format of various image types, refer to MEDIA_BUS_FMT 表

10.2.2.4 xxxx_enum_frame_sizes

[description]

Enumerate sensor output size.

[grammar]

  static int xxxx_enum_frame_sizes(struct v4l2_subdev *sd,
                              struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_frame_size_enum *fse)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
*cfg subdev pad information structure pointer input
*fse media bus frame size structure pointer output

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.5 xxxx_g_frame_interval

[description]

Get the sensor output fps.

[grammar]

  static int xxxx_g_frame_interval(struct v4l2_subdev *sd,
                                   struct v4l2_subdev_frame_interval *fi)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
*fi pad-level frame rate structure pointer output

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.6 xxxx_s_stream

[description]

Set stream input and output.

[grammar]

  static int xxxx_s_stream(struct v4l2_subdev *sd, int on)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
on 1: Start stream output; 0: Stop stream output Input

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.7 xxxx_runtime_resume

[description]

The callback function when the sensor is powered on.

[grammar]

  static int xxxx_runtime_resume(struct device *dev)

[parameter]

Parameter name Description Input and output
*dev device structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.8 xxxx_runtime_suspend

[description]

The callback function when the sensor is powered off.

[grammar]

  static int xxxx_runtime_suspend(struct device *dev)

[parameter]

Parameter name Description Input and output
*dev device structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.9 xxxx_set_ctrl

[description]

Set the value of each control.

[grammar]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2_ctrl structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.10 xxx_enum_frame_interval

[description]

Enumerate the frame interval parameters supported by the sensor.

[grammar]

  static int xxxx_enum_frame_interval(struct v4l2_subdev *sd,
                      struct v4l2_subdev_pad_config *cfg,
                      struct v4l2_subdev_frame_interval_enum *fie)

[parameter]

Parameter name Description Input and output
*sd Sub-device instance Input
*cfg pad configuration parameters input
*fie Frame interval parameter Output

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.11 xxxx_g_mbus_config

[description]

Obtain the supported bus configuration. For example, when MIPI is used, when the Sensor supports multiple MIPI transmission modes, the parameters can be uploaded according to the MIPI mode currently used by the Sensor.

[grammar]

  static int xxxx_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)

[parameter]

Parameter name Description Input and output
*config Bus configuration parameters Output

[return value]

Return value Description
0 Success
Not 0 Failed
10.2.2.12 xxxx_get_selection

[description]

Configure the cropping parameters. The width of the ISP input requires 16 alignment and the height 8 alignment. For the sensor output resolution that does not meet the alignment or the sensor output resolution is not a standard resolution, this function can be implemented to crop the input isp resolution.

[grammar]

  static int xxxx_get_selection(struct v4l2_subdev *sd,
  struct v4l2_subdev_pad_config *cfg,
  struct v4l2_subdev_selection *sel)

[parameter]

Parameter name Description Input and output
*sd Sub-device instance Input
*cfg pad configuration parameters input
*sel Cutting parameters Output

[return value]

Return value Description
0 Success
Not 0 Failed

10.2.3 Drive migration steps

1. Implement the standard I2C sub-device driver part.

1.1 Implement the following members according to struct i2c_driver instructions:

struct driver.name

struct driver.pm

struct driver. of_match_table

probe function

remove function

1.2 Detailed description of the probe function implementation: 1). The acquisition of CIS equipment resources is mainly to analyze the resources defined in the DTS file, refer to CIS Device Registration (DTS).

1.1) RK private resource definition, the naming method is as follows: rockchip, camera-module-xxx, this part of the resource will be uploaded to the camera_engine in the user mode by the driver to determine the matching of the IQ effect parameters;

1.2) CIS equipment resource definition, RK related reference drivers generally include the following items:

Member name Description
CIS device working reference clock The external independent crystal oscillator solution does not need to be obtained. The RK reference design generally uses the AP output clock. This solution needs to be obtained, and the general name is xvclk
CIS device control GPIO For example: Resst pin, Powerdown pin
CIS equipment control power supply According to the actual hardware design, obtain matching software power control resources, such as gpio, regulator

1.3) CIS device ID number check. After obtaining the necessary resources through the above steps, it is recommended that the driver read the device ID number to check the accuracy of the hardware. Of course, this step is not necessary.

1.4) Initialization of CIS v4l2 equipment and media entities;

v4l2 sub-device: v4l2_i2c_subdev_init, RK CIS driver requires subdev to have its own device node for user mode rk_aiq to access, and realize exposure control through this device node;

media entity: media_entity_init

2. Refer to struct v4l2_subdev_ops instructions to implement the v4l2 sub-device driver, which mainly implements the following 3 members:

  struct v4l2_subdev_core_ops
  struct v4l2_subdev_video_ops
  struct v4l2_subdev_pad_ops

2.1 Refer to struct v4l2_subdev_core_ops to explain the implementation of its callback function, which mainly implements the following callbacks:

.s_power.ioctl
.compat_ioctl32

The RK private control commands mainly implemented by ioctl involve:

成员名称 描述
RKMODULE_GET_MODULE_INFO The module information defined by the DTS file (module name, etc.), upload camera_engine through this command
RKMODULE_AWB_CFG When the module OTP information is enabled, the camera_engine transmits the typical module AWB calibration value through this command, and the CIS driver is responsible for comparing with the current module AWB calibration value, and then generate the R/B Gain value and set it to the CIS MWB module;
RKMODULE_LSC_CFG When the module OTP information is enabled, camera_engine controls the LSC calibration value to be enabled through this command;
PREISP_CMD_SET_HDRAE_EXP Refer to this document for details on HDR exposure settings struct preisp_hdrae_exp_s
RKMODULE_SET_HDR_CFG Set HDR mode, can realize normal and HDR switch, need to drive to adapt HDR and normal 2 sets of configuration information, please refer to this document for details struct rkmodule_hdr_cfg
RKMODULE_GET_HDR_CFG Get the current HDR mode and refer to this document struct rkmodule_hdr_cfg
RKMODULE_SET_CONVERSION_GAIN Set the conversion gain of linear mode, such as imx347, os04a10 sensor with conversion gain function, high conversion conversion gain can get a better signal-to-noise ratio under low illumination, if the sensor does not support conversion gain, it may not be realized

2.2 Refer to struct v4l2_subdev_video_ops to explain the realization of its callback function, which mainly realizes the following callback functions:

Member name Description
.s_stream The function to switch the data stream. For mipi clk is a continuous mode, the data stream must be opened in this callback function. If the data stream is opened in advance, the MIPI LP status will not be recognized
.g_frame_interval Get frame interval parameters (frame rate)
.g_mbus_config Get the bus configuration. For the MIPI interface, if the sensor driver supports different lane configurations or supports HDR, this interface returns the MIPI configuration in the current sensor working mode

2.3 Refer to struct v4l2_subdev_pad_ops to explain the realization of its callback function, mainly to realize the following callback functions:

Member name Description
.enum_mbus_code Enumerate data formats supported by the current CIS driver
.enum_frame_size Enumerate the resolutions supported by the current CIS driver
.get_fmt RKISP driver obtains the data format output by CIS through this callback, which must be realized; for the definition of data type output by Bayer raw sensor, SOC yuv sensor, and BW raw sensor, please refer to MEDIA_BUS_FMT table for field output mode Support, refer to struct v4l2_mbus_framefmt definition;
.set_fmt Set the output data format and resolution of the CIS driver, which must be realized
.enum_frame_interval Enumerate the frame interval supported by the sensor, including the resolution
.get_selection Configure the cropping parameters, the width of the ISP input requires 16 alignment, and the height 8 alignment

2.4 Refer to the description of struct v4l2_ctrl_ops to implement, mainly implement the following callbacks

Member name Description
.s_ctrl RKISP driver and camera_engine realize CIS exposure control by setting different commands;

Refer to CIS driver V4L2-controls list to implement each control ID. The following IDs belong to the information acquisition category, and this part of the implementation is implemented in accordance with standard integer menu controls;

Member name Description
V4L2_CID_LINK_FREQ Refer to the standard definition inCIS driver V4L2-controls list, currently RKISP driver obtains MIPI bus frequency according to this command;
V4L2_CID_PIXEL_RATE For MIPI bus: pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
V4L2_CID_HBLANK Refer to the standard definition inCIS driver V4L2-controls list
V4L2_CID_VBLANK Refer to the standard definition in CIS driver V4L2-controls list

RK camera_engine will obtain the necessary information to calculate the exposure through the above command, and the formula involved is as follows:

Formula
line_time = HTS / PIXEL_RATE;
PIXEL_RATE = HTS * VTS * FPS
HTS = sensor_width_out + HBLANK;
VTS = sensor_height_out + VBLANK;

Among them, the following IDs belong to the control category, and RK camera_engine controls CIS through this type of command

Member name Description
V4L2_CID_VBLANK Adjust VBLANK, and then adjust frame rate and Exposure time max;
V4L2_CID_EXPOSURE Set the exposure time, unit: number of exposure lines
V4L2_CID_ANALOGUE_GAIN Set exposure gain, actually total gain = analog gain*digital gain; Unit: gain register value

3. CIS driver does not involve the definition of hardware data interface information. The interface connection relationship between CIS device and AP is reflected by the port of the DTS device node. Refer to CIS Device Registration (DTS) Description of Port information. 4. CIS Reference Driver List

11. VCM Drive

11.1 VCM Device Registration (DTS)

RK VCM driver private parameter description:

Name Description
Starting current VCM can just drive the module lens to move from the nearest end of the movable stroke of the module lens (module far focus). At this time, the output current value of the VCM driver ic is defined as the starting current
Rated current VCM just pushes the module lens to the far end of the movable stroke of the module lens (the module is near focus), at this time the output current value of the VCM driver ic is defined as the rated current
VCM current output mode Oscillation occurs during VCM movement. VCM driver ic current output changes need to consider the oscillation period of vcm to minimize oscillation. The output mode determines the time for the output current to change to the target value;
  vm149c: vm149c@0c { // vcm driver configuration, this set up is required when supporting AF
      compatible = "silicon touch,vm149c";
      status = "okay";
      reg = <0x0c>;
      rockchip,vcm-start-current = <0>;// Starting current of the motor
      rockchip,vcm-rated-current = <100>; // Motor rated current
      rockchip,vcm-step-mode = <4>; // Current output mode of motor drive IC
      rockchip,camera-module-index = <0>; // Module number
      rockchip,camera-module-facing = "back"; // Module orientation, there are "back" and "front"
  };
  ov13850: ov13850@10 {
      ......
      lens-focus = <&vm149c>; // vcm driver set up, need to have this set up when supporting AF
      ......
  };

11.2 VCM driver description

11.2.1 Brief description of data type

11.2.1.1 struct i2c_driver

[Description]

Define i2c device driver information

[Definition]

  struct i2c_driver {
      ……
      /* Standard driver model interfaces */
      int (*probe)(struct i2c_client *, const struct i2c_device_id *);
      int (*remove)(struct i2c_client *);
      ……
      struct device_driver driver;
      const struct i2c_device_id *id_table;
      ……
  };

[Key Member]

Member name Description
@driver Device driver model driver mainly contains the name of the driver and the of_match_table that matches the DTS registered device. When the compatible field in of_match_table matches the compatible field in the dts file, the .probe function will be called
@id_table List of I2C devices supported by this driver If the kernel does not use of_match_table and dts registered devices for matching, the kernel uses this table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  static const struct i2c_device_id vm149c_id_table[] = {
      { VM149C_NAME, 0 },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(i2c, vm149c_id_table);
  static const struct of_device_id vm149c_of_table[] = {
      { .compatible = "silicon touch,vm149c" },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(of, vm149c_of_table);
  static const struct dev_pm_ops vm149c_pm_ops = {
      SET_SYSTEM_SLEEP_PM_OPS(vm149c_vcm_suspend, vm149c_vcm_resume)
      SET_RUNTIME_PM_OPS(vm149c_vcm_suspend, vm149c_vcm_resume, NULL)
  };
  static struct i2c_driver vm149c_i2c_driver = {
      .driver = {
          .name = VM149C_NAME,
          .pm = &vm149c_pm_ops,
          .of_match_table = vm149c_of_table,
      },
      .probe = &vm149c_probe,
      .remove = &vm149c_remove,
      .id_table = vm149c_id_table,
  };
  module_i2c_driver(vm149c_i2c_driver);
11.2.1.2 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
                             unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name Description
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops vm149c_core_ops = {
      .ioctl = vm149c_ioctl,
  #ifdef CONFIG_COMPAT
      .compat_ioctl32 = vm149c_compat_ioctl32
  #endif
  };

At present, the following private ioctl is used to query the time information of the motor movement.

RK_VIDIOC_VCM_TIMEINFO
11.2.1.3 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
     int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
     int (*try_ctrl)(struct v4l2_ctrl *ctrl);
     int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name Description
.g_volatile_ctrl Get a new value for this control. Generally only relevant for volatile (and usually read- only) controls such as a control that returns the current signal strength which changes continuously.
.s_ctrl Actually set the new control value. s_ctrl is compulsory. The ctrl->handler->lock is held when these ops are called, so no one else can access controls owned by that handler.

[Example]

  static const struct v4l2_ctrl_ops vm149c_vcm_ctrl_ops = {
      .g_volatile_ctrl = vm149c_get_ctrl,
      .s_ctrl = vm149c_set_ctrl,
  };

vm149c_get_ctrl and vm149c_set_ctrl support the following controls

V4L2_CID_FOCUS_ABSOLUTE

11.2.2 API brief description

11.2.2.1 xxxx_get_ctrl

[description]

Get the moving position of the motor.

[grammar]

  static int xxxx_get_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer output

[return value]

Return value Description
0 Success
Not 0 Failed
11.2.2.2 xxxx_set_ctrl

[description]

Set the moving position of the motor.

[grammar]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
11.2.2.3   xxxx_ioctl xxxx_compat_ioctl

[description]

The realization function of custom ioctl mainly includes obtaining the time information of motor movement,

Implemented a custom RK_VIDIOC_COMPAT_VCM_TIMEINFO.

[grammar]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
cmd ioctl command input
*arg/arg Parameter pointer Output

[return value]

Return value Description
0 Success
Not 0 Failed

11.2.3 Drive migration steps

1. Implement the standard i2c sub-device driver part.

1.1 According to the description of struct i2c_driver, the following parts are mainly realized:

struct driver.name

struct driver.pm

struct driver. of_match_table

probe function

remove function

1.2 Detailed description of the probe function implementation:

1. Acquisition of VCM equipment resources, mainly to obtain DTS resources, refer to VCM device registration(DTS)

1.1) RK private resource definition, naming methods such as rockchip, camera-module-xxx, mainly to provide equipment parameters and Camera equipment to match.

1.2) VCM parameter definition, naming methods such as rockchip, vcm-xxx, mainly related to hardware parameters start current, rated current, movement mode, parameters are related to the range and speed of motor movement.

2. Initialization of VCM v4l2 device and media entity.

v4l2 sub-device: v4l2_i2c_subdev_init, the RK VCM driver requires subdev to have its own device node for user- mode camera_engine to access, and realize focusing control through this device node;

media entity: media_entity_init;

3. The RK AF algorithm defines the position parameter of the entire movable stroke of the module lens as [0,64]. The corresponding variation range of the entire movable stroke of the module lens on the VCM drive current is [starting current, rated current]. It is recommended to implement the mapping conversion relationship between these two in the function;

2. Implement the v4l2 sub-device driver, which mainly implements the following 2 members:

  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Refer to v4l2_subdev_core_ops to explain the implementation of the callback function, which mainly implements the following callback functions:

.ioctl.compat_ioctl32

This callback mainly implements RK private control commands, involving:

Member name Description
RK_VIDIOC_VCM_TIMEINFO camera_engine uses this command to obtain the time required for the lens movement, and judges when the lens stops and whether the CIS frame exposure time period overlaps with the lens movement time period based on this command; lens movement time and lens movement distance, VCM driver ic The current output mode is related.

2.2 Refer to the description of v4l2_ctrl_ops to implement the callback function, which mainly implements the following callback functions:

.g_volatile_ctrl.s_ctrl

.g_volatile_ctrl and .s_ctrl implement the following commands with standard v4l2 control:

Member name Description
V4L2_CID_FOCUS_ABSOLUTE camera_engine uses this command to set and obtain the absolute position of the lens. In the RK AF algorithm, the position parameter of the entire movable stroke of the lens is defined as [0,64].

12. FlashLight driver

12.1 FLASHLight Device Registration (DTS)

SGM378 DTS reference:

  &i2c1 {
      ...
      sgm3784: sgm3784@30 {//Flash equipment
          #address-cells = <1>;
          #size-cells = <0>;
          compatible = "sgmicro,gsm3784";
          reg = <0x30>;
          rockchip,camera-module-index = <0>;//The flash corresponds to the camera module number
          rockchip,camera-module-facing = "back";//The flash corresponds to the orientation of the camera module
          enable-gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;//enable gpio
          strobe-gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;//flash trigger gpio
          status = "okay";
          sgm3784_led0: led@0 {//led0 device information
              reg = <0x0>;//index
              led-max-microamp = <299200>;//Torch mode maximum current
              flash-max-microamp = <1122000>;//flash mode maximum current
              flash-max-timeout-us = <1600000>;//maximum flash time
          };
          sgm3784_led1: led@1 {//led1 device information
              reg = <0x1>;//index
              led-max-microamp = <299200>;//Torch mode maximum current
              flash-max-microamp = <1122000>;//flash mode maximum current
              flash-max-timeout-us = <1600000>;//maximum flash time
          };
      };
      ...
      ov13850: ov13850@10 {
          ...
          flash-leds = <&sgm3784_led0 &sgm3784_led1>;//The flash device is hooked to the camera
          ...
      };
      ...
  }

GPIO, PWM control dts reference:

  flash_ir: flash-ir {
          status = "okay";
          compatible = "led,rgb13h";
          label = "pwm-flash-ir";
          led-max-microamp = <20000>;
          flash-max-microamp = <20000>;
          flash-max-timeout-us = <1000000>;
          pwms=<&pwm3 0 25000 0>;
          //enable-gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
  };
  &i2c1 {
      imx415: imx415@1a {
          ...
          flash-leds = <&flash_ir>;
          ...
      }
  }

Note:

1. The software needs to distinguish the processing flow according to the type of the fill light. If it is an infrared fill light, the dts fill light node label needs to have the word ir to identify the hardware type, and the ir field of the led fill light can be removed.

2. For this single-pin controlled hardware circuit, there are two situations, one is to fix the brightness, directly use gpio control. The other is the brightness controllable, using pwm, set the brightness by adjusting the duty cycle, dts pwms or enable-gpio, choose one of the two configurations.

12.2 FLASHLight driver description

12.2.1 Brief description of data type

12.2.1.1 struct i2c_driver

[Description]

Define i2c device driver information

[Definition]

  struct i2c_driver {
      ……
      /* Standard driver model interfaces */
      int (*probe)(struct i2c_client *, const struct i2c_device_id *);
      int (*remove)(struct i2c_client *);
      ……
      struct device_driver driver;
      const struct i2c_device_id *id_table;
      ……
  };

[Key Member]

Member name Description
@driver Device driver model driver mainly contains the name of the driver and the of_match_table that matches the DTS registered device. When the compatible field in of_match_table matches the compatible field in the dts file, the .probe function will be called
@id_table List of I2C devices supported by this driver If the kernel does not use of_match_table and dts registered devices for matching, the kernel uses this table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  static const struct i2c_device_id sgm3784_id_table[] = {
      { SGM3784_NAME, 0 },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(i2c, sgm3784_id_table);
  static const struct of_device_id sgm3784_of_table[] = {
      { .compatible = "sgmicro,sgm3784" },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(of, sgm3784_of_table);
  static const struct dev_pm_ops sgm3784_pm_ops = {
      SET_RUNTIME_PM_OPS(sgm3784_runtime_suspend, sgm3784_runtime_resume, NULL)
  };
  static struct i2c_driver sgm3784_i2c_driver = {
      .driver = {
          .name = sgm3784_NAME,
          .pm = &sgm3784_pm_ops,
          .of_match_table = sgm3784_of_table,
      },
      .probe = &sgm3784_probe,
      .remove = &sgm3784_remove,
      .id_table = sgm3784_id_table,
  };
  module_i2c_driver(vm149c_i2c_driver);
12.2.1.2 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name Description
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops sgm3784_core_ops = {
      .ioctl = sgm3784_ioctl,
  #ifdef CONFIG_COMPAT
      .compat_ioctl32 = sgm3784_compat_ioctl32
  #endif
  };

Currently, the following private ioctl is used to query the flash lighting time information.

RK_VIDIOC_FLASH_TIMEINFO
12.2.1.3 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
      int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name Description
.g_volatile_ctrl Get a new value for this control. Generally only relevant for volatile (and usually read- only) controls such as a control that returns the current signal strength which changes continuously.
.s_ctrl Actually set the new control value. s_ctrl is compulsory. The ctrl->handler->lock is held when these ops are called, so no one else can access controls owned by that handler.

[Example]

  static const struct v4l2_ctrl_ops sgm3784_ctrl_ops[LED_MAX] = {
      [LED0] = {
          .g_volatile_ctrl = sgm3784_led0_get_ctrl,
          .s_ctrl = sgm3784_led0_set_ctrl,
      },
      [LED1] = {
          .g_volatile_ctrl = sgm3784_led1_get_ctrl,
          .s_ctrl = sgm3784_led1_set_ctrl,
      }
  };

12.2.2 API brief description

12.2.2.1 xxxx_set_ctrl

[description]

Set the flash mode, current and flash timeout time.

[grammar]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
12.2.2.2 xxxx_get_ctrl

[description]

Get the flash fault status.

[grammar]

  static int xxxx_get_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer output

[return value]

Return value Description
0 Success
Not 0 Failed
12.2.2.3   xxxx_ioctl xxxx_compat_ioctl

[description]

The implementation function of custom ioctl mainly includes obtaining the time information of the flash light,

Implemented a custom RK_VIDIOC_COMPAT_FLASH_TIMEINFO.

[grammar]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
cmd ioctl command input
*arg/arg Parameter pointer Output

[return value]

Return value Description
0 Success
Not 0 Failed

12.2.3 Drive migration steps

For ordinary gpio to directly control leds, please refer to kernel/drivers/leds/leds-rgb13h.c and kernel/Documentation/devicetree/bindings/leds/leds-rgb13h.txt

The flashlight driver IC can be transplanted as follows

1. Implement the standard i2c sub-device driver part.

1.1 According to the description of struct i2c_driver, the following parts are mainly realized:

struct driver.name

struct driver.pm

struct driver. of_match_table

probe function

remove function

1.2 Detailed description of the probe function implementation:

1. Acquisition of flashlight device resources, mainly to obtain DTS resources, refer to FLASHLIGHT device registration (DTS);

1.1) RK private resource definition, naming methods such as rockchip, camera-module-xxx, mainly to provide equipment parameters and Camera equipment to match.

2. Flash device name:

For dual led flash, use led0 and led1 device names to distinguish.

  /* NOTE: to distinguish between two led
   * name: led0 meet the main led
   * name: led1 meet the secondary led
   */
  snprintf(sd->name, sizeof(sd->name),
           "m%02d_%s_%s_led%d %s",
           flash->module_index, facing,
           SGM3784_NAME, i, dev_name(sd->dev));

3. Initialization of FLASH v4l2 device and media entity.

v4l2 sub-device: v4l2_i2c_subdev_init, the RK flashlight driver requires subdev to have its own device node for user-mode camera_engine to access, and realize led control through this device node;

media entity: media_entity_init;

2. Implement the v4l2 sub-device driver, which mainly implements the following 2 members:

  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Refer to v4l2_subdev_core_ops to explain the implementation of the callback function, which mainly implements the following callback functions:

.ioctl.compat_ioctl32

This callback mainly implements RK private control commands, involving:

Member name Description
RK_VIDIOC_FLASH_TIMEINFO camera_engine uses this command to obtain the time when the LED is on, and then judges whether the CIS frame exposure time is after the flash is on.

2.2 Refer to the description of v4l2_ctrl_ops to implement the callback function, which mainly implements the following callback functions:

.g_volatile_ctrl.s_ctrl

.g_volatile_ctrl and .s_ctrl implement the following commands with standard v4l2 control:

Member name Description
V4L2_CID_FLASH_FAULT Get flash fault information
V4L2_CID_FLASH_LED_MODE Set LED mode V4L2_FLASH_LED_MODE_NONE V4L2_FLASH_LED_MODE_TORCH V4L2_FLASH_LED_MODE_FLASH
V4L2_CID_FLASH_STROBE Control the flashlight on
V4L2_CID_FLASH_STROBE_STOP Control flash off
V4L2_CID_FLASH_TIMEOUT Set the maximum continuous light time of flash mode
V4L2_CID_FLASH_INTENSITY Set flash mode current
V4L2_CID_FLASH_TORCH_INTENSITY Set Torch Mode Current

13. FOCUS ZOOM P-IRIS driver

The drive here refers to the auto focus (FOCUS), zoom (ZOOM), and auto iris (P-IRIS) controlled by a stepping motor. Due to the same stepping motor control method and hardware design factors, the three function drives are integrated into one drive. According to the driver chip used, such as a SPI controlled chip, the driver can be packaged into a SPI frame sub-device. This chapter describes the data structure, framework and precautions that the driver needs to implement around the MP6507 and MS41908 driver chips.

13.1 MP6507 device registration(DTS)

  mp6507: mp6507 {
      status = "okay";
      compatible = "monolithicpower,mp6507";
      #pwm-cells = <3>;
      pwms = <&pwm6 0 25000 0>,
             <&pwm10 0 25000 0>,
             <&pwm9 0 25000 0>,
             <&pwm8 0 25000 0>;
      pwm-names = "ain1","ain2","bin1","bin2";
      rockchip,camera-module-index = <1>;
      rockchip,camera-module-facing = "front";
      iris_en-gpios  = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>;
      focus_en-gpios  = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;
      zoom_en-gpios  = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
      iris-step-max = <80>;
      focus-step-max = <7500>;
      zoom-step-max = <7500>;
      iris-start-up-speed = <1200>;
      focus-start-up-speed = <1200>;
      focus-max-speed = <2500>;
      zoom-start-up-speed = <1200>;
      zoom-max-speed = <2500>;
      focus-first-speed-step = <8>;
      zoom-first-speed-step = <8>;
      focus-speed-up-table = < 1176 1181 1188 1196
                               1206 1217 1231 1246
                               1265 1286 1309 1336
                               1365 1396 1429 1464
                               1500 1535 1570 1603
                               1634 1663 1690 1713
                               1734 1753 1768 1782
                               1793 1803 1811 1818>;
      focus-speed-down-table = < 1796 1788 1779 1768
                                 1756 1743 1728 1712
                                 1694 1674 1653 1630
                                 1605 1580 1554 1527
                                 1500 1472 1445 1419
                                 1394 1369 1346 1325
                                 1305 1287 1271 1256
                                 1243 1231 1220 1211
                                 1203 1195 1189 1184
                                 1179 1175>;
      zoom-speed-up-table = < 1198 1205 1212 1220
                              1228 1238 1249 1260
                              1272 1285 1299 1313
                              1328 1343 1359 1375
                              1390 1406 1421 1436
                              1450 1464 1477 1489
                              1500 1511 1521 1529
                              1537 1544 1551>;
      zoom-speed-down-table = < 1547 1540 1531 1522
                                1511 1499 1487 1473
                                1458 1443 1426 1409
                                1392 1375 1357 1340
                                1323 1306 1291 1276
                                1262 1250 1238 1227
                                1218 1209 1202 1195
                                1189 1184 1179 1175
                                1171 1168>;
  };
  &i2c1 {
      imx334: imx334@1a {
          ...
          lens-focus = <&mp6507>;
          ...
      }
  }
  &pwm6 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm6m1_pins_pull_up>;
  };
  &pwm8 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm8m1_pins_pull_down>;
      center-aligned;
  };
  &pwm9 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm9m1_pins_pull_down>;
      center-aligned;
  };
  &pwm10 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm10m1_pins_pull_down>;
  };

RK private definition description:

Member name Description
rockchip, camera-module- index camera serial number, field matching camera
rockchip, camera-module- facing camera orientation, field matching camera
iris_en-gpios IRIS enable GPIO
focus_en-gpios focus enable GPIO
zoom_en-gpios zoom enable GPIO
rockchip,iris- step-max P-IRIS stepper motor moves the maximum number of steps
rockchip,focus- step-max The maximum number of steps the focus stepper motor can move
zoom-step-max The maximum number of steps that the zoom stepper motor can move
iris-start-up- speed Starting speed of the stepper motor used by IRIS
focus-start-up- speed Starting speed of the stepper motor used by focus
focus-max-speed The maximum operating speed of the stepper motor used by focus
zoom-start-up- speed Starting speed of the stepper motor used by zoom
zoom-max-speed The maximum operating speed of the stepping motor used by zoom
focus-first-speed- step The number of steps at which focus starts speed, and the number of steps is increased proportionally in the subsequent acceleration interval, so that the running time of each speed stage is as close as possible to the same
zoom-first-speed- step The number of steps at the start speed of zoom, and the number of steps is increased proportionally in the subsequent acceleration interval, so that the running time of each speed stage is as close as possible to the same
focus-speed-up- table The focus acceleration curve uses the table lookup method, adjusts the parameters to generate the acceleration curve, and configures the generated trapezoidal acceleration curve or the S-shaped acceleration curve data table. If you do not configure or configure a single data, just press The starting speed runs at a constant speed; the minimum value of the acceleration curve does not exceed the maximum starting speed of the motor, and the maximum value does not exceed the maximum operating speed of the stepper motor.
Member name Description
focus-speed- down-table focus deceleration curve, the maximum value of the deceleration curve must be less than the maximum value of the acceleration curve; if the acceleration curve is invalid, the deceleration curve is also invalid, and the whole process runs at a constant speed at the starting speed; if there is no deceleration curve configured, the deceleration curve is decelerated The curve is obtained symmetrically from the acceleration curve.
zoom-speed-up- table zoom acceleration curve adopts table lookup method, adjusts parameters to generate acceleration curve, and configures the generated trapezoidal acceleration curve or S- shaped acceleration curve data table. If you do not configure or configure a single data, press directly The starting speed runs at a constant speed; the minimum value of the acceleration curve does not exceed the maximum starting speed of the motor, and the maximum value does not exceed the maximum operating speed of the stepper motor.
zoom-speed- down-table zoom deceleration curve, the maximum value of the deceleration curve must be less than the maximum value of the acceleration curve; if the acceleration curve is invalid, the deceleration curve is also invalid, and the whole process runs at the starting speed at a constant speed; if there is no deceleration curve configured, the deceleration curve is decelerated The curve is obtained symmetrically from the acceleration curve.

13.1.1 Brief description of data type

13.1.1.1 struct platform_driver

[Description]

Define platform device driver information

[Definition]

  struct platform_driver {
          int (*probe)(struct platform_device *);
          int (*remove)(struct platform_device *);
          void (*shutdown)(struct platform_device *);
          int (*suspend)(struct platform_device *, pm_message_t state);
          int (*resume)(struct platform_device *);
          struct device_driver driver;
          const struct platform_device_id *id_table;
          bool prevent_deferred_probe;
  };

[Key Member]

Member name Description
@driver struct device_driver driver mainly contains the name of the driver and of_match_table for matching with DTS registered devices. When the compatible field in of_match_table matches the compatible field in the dts file, the .probe function will be called
@id_table If the kernel does not use of_match_table and dts registered equipment for matching, the kernel uses the table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  #if defined(CONFIG_OF)
  static const struct of_device_id motor_dev_of_match[] = {
      { .compatible = "monolithicpower,mp6507", },
      {},
  };
  #endif
  static struct platform_driver motor_dev_driver = {
      .driver = {
          .name = DRIVER_NAME,
          .owner = THIS_MODULE,
          .of_match_table = of_match_ptr(motor_dev_of_match),
      },
      .probe = motor_dev_probe,
      .remove = motor_dev_remove,
  };
  module_platform_driver(motor_dev_driver);
13.1.1.2 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name Description
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops motor_core_ops = {
      .ioctl = motor_ioctl,
  };
  static const struct v4l2_subdev_ops motor_subdev_ops = {
      .core   = &motor_core_ops,
  };
13.1.1.3 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
      int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name Description
.g_volatile_ctrl Get a new value for this control. Generally only relevant for volatile (and usually read- only) controls such as a control that returns the current signal strength which changes continuously.
.s_ctrl Actually set the new control value. s_ctrl is compulsory. The ctrl->handler->lock is held when these ops are called, so no one else can access controls owned by that handler.

[Example]

  static const struct v4l2_ctrl_ops motor_ctrl_ops = {
      .s_ctrl = motor_s_ctrl,
  };

13.1.2 API brief description

13.1.2.1 xxxx_set_ctrl

[description]

Call standard v4l2_control to set focus, zoom, and P aperture position.

The following v4l2 standard commands are implemented:

Member name Description
V4L2_CID_FOCUS_ABSOLUTE Control the focus, 0 means the smallest focal length, clear close up
V4L2_CID_ZOOM_ABSOLUTE Control the zoom factor, 0 means the zoom factor is the smallest and the field of view is the largest
V4L2_CID_IRIS_ABSOLUTE Control the size of the P aperture opening, 0 means the aperture is closed

[grammar]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
13.1.2.2 xxxx_get_ctrl

[description]

Call standard v4l2_control to get the current position of focus, zoom and P aperture.

The following v4l2 standard commands are implemented:

Member name Description
V4L2_CID_FOCUS_ABSOLUTE Control the focus, 0 means the smallest focal length, clear close up
V4L2_CID_ZOOM_ABSOLUTE Control the zoom factor, 0 means the zoom factor is the smallest and the field of view is the largest
V4L2_CID_IRIS_ABSOLUTE Control the size of the P aperture opening, 0 means the aperture is closed

[grammar]

  static int xxxx_get_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer output

[return value]

Return value Description
0 Success
Not 0 Failed
13.1.2.3   xxxx_ioctl xxxx_compat_ioctl

[description]

The realization function of custom ioctl mainly includes the time information of obtaining focus, zoom and P aperture (time stamp of start and end movement). Since the lens used does not have a positioning device, it is necessary to reset the position of the lens motor when necessary .

Implemented customization:

Member name Description
RK_VIDIOC_VCM_TIMEINFO Focusing time information, used to confirm whether the current frame is the effective frame after focusing
RK_VIDIOC_ZOOM_TIMEINFO Zoom time information, used to confirm whether the current frame is the effective frame after zooming
RK_VIDIOC_IRIS_TIMEINFO Time information of the aperture, used to confirm whether the current frame is the effective frame after aperture adjustment
RK_VIDIOC_FOCUS_CORRECTION Focus position correction (reset)
RK_VIDIOC_ZOOM_CORRECTION Zoom position correction (reset)
RK_VIDIOC_IRIS_CORRECTION Iris position correction (reset)

[grammar]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
cmd ioctl command input
*arg/arg Parameter pointer Output

[return value]

Return value Description
0 Success
Not 0 Failed

13.1.3 Drive migration steps

For SPI-controlled driver chips, you can use the SPI framework for device driver transplantation. The RK reference driver uses MP6507, directly uses pwm to output the control waveform, and uses MP6507 for power amplification, so the platform framework is directly transplanted. Driver reference: /kernel/drivers/media/i2c/mp6507.c

The migration steps are as follows:

1. Implement the standard platform sub-device driver part.

1.1 According to the description of struct platform_driver, the following parts are mainly realized:

struct driver.name

struct driver. of_match_table

probe function

remove function

1.2 Detailed description of the probe function implementation:

1. Acquisition of equipment resources, mainly to obtain DTS resources, refer to MP6507 device registration(DTS);

1.1) RK private resource definition, naming methods such as rockchip, camera-module-xxx, mainly to provide equipment parameters and Camera equipment to match.

1.2) Obtain the pwm configuration. According to the control method of the motor, the phase difference of AB phase is 90 degrees. This can be achieved by aligning the center of the PWM setting of the B phase. Configure center-aligned at the dts pwm node. For details, seeMP6507 device registration(DTS);

Motor excitation sequence and winding connections — original English figure, PDF page 163

Motor excitation sequence and winding connections — original English figure, PDF page 163

Excitation sequence; output shaft rotation CW.

Phase / step 1 2 3 4
A + + − −
A̅ − − + +
B − + + −
B̅ + − − +

1.3) To obtain the enable pin, MP6507 needs to use 4 PWMs to generate stepper motor control waveforms. Due to the limited hardware PWM, the focus, zoom, and P iris stepper motors each use a MP6507 driver to drive, so use gpio to enable It can correspond to the MP6507 driver, so as to realize PWM time-sharing multiplexing. Of course, this also has a drawback. Only one stepper motor can be driven at the same time, and the other two stepper motors need to wait for the end of the previous operation to continue operation; 1.4) Obtain hardware-related constraints and resources such as the maximum step, maximum starting speed, maximum operating speed, acceleration curve data of each motor;

2. hrtimer_init, timer initialization, pwm uses continuous mode, timer timing is required, after reaching the specified number of output pwm waveforms, the timer interrupt closes pwm, and the acceleration process also needs to enter timing after the specified number of waveforms The device interrupts to modify the pwm frequency, so as to realize the acceleration of the stepper motor;

3. init_completion, the synchronization mechanism is realized through completion, and the next motor operation can only be carried out after the previous motor movement operation ends;

4. Initialization of v4l2 device and media entity.

v4l2 sub-device: v4l2_i2c_subdev_init, the driver requires subdev to have its own device node for user mode rkaiq to access, and realize the control of the motor through this device node;

media entity: media_entity_init;

5. Flash device name:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           motor->module_index, facing,
           DRIVER_NAME);

2. Implement the v4l2 sub-device driver, which mainly implements the following 2 members:

  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Refer to v4l2_subdev_core_ops to explain the implementation of the callback function, which mainly implements the following callback functions:

  .ioctl
  .compat_ioctl32

This callback mainly implements RK private control commands, involving:

Member name Description
RK_VIDIOC_VCM_TIMEINFO Focusing time information, used to confirm whether the current frame is the effective frame after focusing
RK_VIDIOC_ZOOM_TIMEINFO Zoom time information, used to confirm whether the current frame is the effective frame after zooming
RK_VIDIOC_IRIS_TIMEINFO Time information of the aperture, used to confirm whether the current frame is the effective frame after aperture adjustment
RK_VIDIOC_FOCUS_CORRECTION Focus position correction (reset)
RK_VIDIOC_ZOOM_CORRECTION Zoom position correction (reset)
RK_VIDIOC_IRIS_CORRECTION Iris position correction (reset)

2.2 Refer to the description of v4l2_ctrl_ops to implement the callback function, which mainly implements the following callback functions:

.g_volatile_ctrl
.s_ctrl

.g_volatile_ctrl and .s_ctrl implement the following commands with standard v4l2 control:

Parameter name Description
V4L2_CID_FOCUS_ABSOLUTE Control the focus, 0 means the smallest focal length, clear close up
V4L2_CID_ZOOM_ABSOLUTE Control the zoom factor, 0 means the zoom factor is the smallest and the field of view is the largest
V4L2_CID_IRIS_ABSOLUTE Control the size of the P aperture opening, 0 means the aperture is closed**

3. Reference for stepping motor acceleration curve:

3.1 Trapezoidal curve You can simply accelerate and decelerate at equal intervals and speeds as shown in the figure.

Trapezoidal motor acceleration — original English figure, PDF page 165

Trapezoidal motor acceleration — original English figure, PDF page 165

3.2 S-curve If the trapezoidal acceleration is not ideal, you can consider the S-shaped acceleration, you can refer to the following formula: Speed = Vmin + ((Vmax-Vmin) / (1 + exp(-fac * (i-Num) / Num)));

among them,

Vmin refers to the motor starting speed Vmax refers to the target speed of the motor fac is the curve coefficient, generally in the range of 4~6, the larger the value, the steeper the middle of the curve i is the speed segment number, if it is divided into 32 segments to accelerate, the value is 0~31 Num is half of the number of speed segments. If divided into 32 segments, num is 16

Motor S-curve acceleration — original English figure, PDF page 165

Motor S-curve acceleration — original English figure, PDF page 165

13.2 MS41908 device registration(DTS)

Because some lenses support PIRIS, FOCUS, ZOOM, ZOOM1 or a combination of DC-IRIS, FOCUS, ZOOM, MS41908 is made into PIRIS, FOCUS, ZOOM, ZOOM1, DC-IRIS functions configurable, and can be loaded and driven multiple times to achieve multiple The combination of driver chips will cause dts to be more complicated. Please read the description of each parameter carefully.

  &spi0 {
      status = "okay";
      pinctrl-names = "default";
      pinctrl-0 = <&spi0m0_clk &spi0m0_cs0n &spi0m0_miso &spi0m0_mosi>;
      //If pinctrl is not configured, confirm whether the default pinctrl is the actual pin group
      assigned-clocks = <&pmucru CLK_SPI0>;
      assigned-clock-rates = <100000000>;
      ms41908: ms41908@00 {
          status = "okay";
          compatible = "relmon,ms41908";
          reg = <0>;
          pinctrl-names = "default";
          focus-start-up-speed = <800>;
          zoom-start-up-speed = <800>;
          focus-step-max = <3160>;
          zoom-step-max = <1520>;
          focus-backlash = <18>;
          vd_fz-period-us = <10000>;
          vd_fz-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
          use-focus;
          use-zoom;
          focus-used-pin = "cd";
          zoom-used-pin = "ab";
      };
  };
  &i2c1 {
      imx335: imx335@1a{
          ...
          lens-focus = <&ms41908>;
          //Multiple device registration,lens-focus = <&ms41908_0 &ms41908_1>;
          ...
      };
  };

13.2.1 Basic description:

Member name description
pinctrl-0 SPI pin definition, according to the actual pin configuration, the pin can be mapped to the spi function ag. pinctrl-0 = <&spi0m0_clk &spi0m0_cs0n &spi0m0_miso &spi0m0_mosi>;
assigned-clocks assigned-clock-rates SPI Clock configuration, it is recommended to configure at 100MHz
reg reg = <0>; to use cs0 reg = <1>; to use cs1
rockchip,camera- module-index Camera serial number, the field that matches the camera
rockchip,camera- module-facing Camera orientation, field matching camera
reset-gpios The reset pin of ms41908 can not be configured when the hardware is fixed and pulled up
vd_fz-period-us The pulse signal period required for the update of the stepping motor drive register. The pulse signal of the two stepping motors is the same. The motor running time exceeds the vd period will cause out of step, and the drive will ensure that the motor’s single motion cycle time is within the vd period

13.2.2 FOCUS description:

Member name description
use-focus Whether to use the focus function
focus-used-pin Each ms41908 chip can drive two stepping motors, the corresponding pin groups are called “ab” and “cd”, according to the actual hardware connection configuration
focus-backlash The error caused by the gear gap, the number of steps to be compensated when the motor direction changes, and the data obtained according to the actual lens test
focus-start-up- speed The starting speed of the stepping motor, in PPS
focus-step-max The effective movement range of the motor, the unit is the number of steps
focus-ppw Set ms41908 output pwm duty cycle, 0-255, the larger the value, the stronger the drive capacity, adjust according to the motor load
focus-phmode Set ms41908 output PWM waveform phase correction, generally not configured, it depends on the situation
focus-micro Set the number of microsteps, divided into 64, 128, 256 subdivisions, the default is 256 subdivisions
focus-reback- distance The focus curve needs to go in the same direction for the position to be accurate. For example, the current position is 100. If you want to go back to 90, you need to go back to 80 and then to 90. The position is accurate. The parameter configured here is the number of steps for multiple callbacks.
focus-1- 2phase- excitation The default motor excitation mode is 2-2 phase excitation, this parameter can be configured using 1-2 phase excitation ag. focus-1-2phase-excitation;
focus-dir- opposite If the current motor movement direction is opposite to the actual focus curve, this parameter can be configured to reverse the motor movement direction ag. focus-dir-opposite;

Optocoupler description:

Member name description
focus-pic The C pin of the optocoupler is used to detect the level transition. The junction point of the level transition is the origin point of the optocoupler
focus-pia The A pin of the optocoupler drives the photodiode. When the optocoupler is calibrated, it should be pulled up, and it should be pulled down during normal operation, otherwise the photodiode will affect the imaging.
focus-pie When the hardware is designed, it can be directly grounded. If it is designed to be controlled by gpio, it needs to configure the pin to be low level.
focus-min- pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual
focus-min- pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual

Note: The lens without optocoupler positioning does not need to configure optocoupler parameters.

13.2.3 ZOOM description:

Member name description
use-zoom Whether to use the zoom function
zoom-used-pin Each ms41908 chip can drive two stepping motors, the corresponding pin groups are called “ab” and “cd”, according to the actual hardware connection configuration
zoom-backlash The error caused by the gear gap, the number of steps to be compensated when the motor direction changes, and the data obtained according to the test
zoom-start-up- speed The starting speed of the stepping motor, in PPS
zoom-step-max The effective movement range of the motor, the unit is the number of steps
zoom-ppw Set ms41908 output pwm duty cycle, 0-255, the larger the value, the stronger the drive capacity, adjust according to the motor load
zoom-phmode Set ms41908 output PWM waveform phase correction, generally not configured, it depends on the situation
zoom-micro Set the number of microsteps, divided into 64, 128, 256 subdivisions, the default is 256 subdivisions
zoom-1-2phase- excitation The default motor excitation mode is 2-2 phase excitation, this parameter can be configured using 1-2 phase excitation ag. zoom-1-2phase-excitation;
zoom-dir- opposite If the current motor movement direction is opposite to the actual focus curve, this parameter can be configured to reverse the motor movement direction ag. zoom-dir-opposite;

Optocoupler description:

Member name description
zoom-pic The C pin of the optocoupler is used to detect the level transition. The junction point of the level transition is the origin point of the optocoupler
zoom-min- pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual
zoom-min- pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual

Note: The lens without optocoupler positioning does not need to configure optocoupler parameters.

13.2.4 ZOOM1 description:

Member name description
use-zoom1 Whether to use the function of zoom1, some lenses support the control of 2 zooms
zoom1-used-pin Each ms41908 chip can drive two stepping motors, the corresponding pin groups are called “ab” and “cd”, according to the actual hardware connection configuration
zoom1-backlash The error caused by the gear gap, the number of steps to be compensated when the motor direction changes, and the data obtained according to the test
zoom1-start-up- speed The starting speed of the stepping motor, in PPS
zoom1-step-max The effective movement range of the motor, the unit is the number of steps
zoom1-ppw Set ms41908 output pwm duty cycle, 0-255, the larger the value, the stronger the drive capacity, adjust according to the motor load
zoom1-phmode Set ms41908 output PWM waveform phase correction, generally not configured, it depends on the situation
zoom1-micro Set the number of microsteps, divided into 64, 128, 256 subdivisions, the default is 256 subdivisions
zoom1-1-2phase- excitation The default motor excitation mode is 2-2 phase excitation, this parameter can be configured using 1-2 phase excitation ag. zoom1-1-2phase-excitation;
zoom1-dir- opposite If the current motor movement direction is opposite to the actual focus curve, this parameter can be configured to reverse the motor movement direction ag. zoom1-dir-opposite;

Optocoupler description:

Member name description
zoom1-pic The C pin of the optocoupler is used to detect the level transition. The junction point of the level transition is the origin point of the optocoupler
zoom1-pia The A pin of the optocoupler drives the photodiode. When the optocoupler is calibrated, it should be pulled up, and it should be pulled down during normal operation, otherwise the photodiode will affect the imaging.
zoom1-pie When the hardware is designed, it can be directly grounded. If it is designed to be controlled by gpio, it needs to configure the pin to be low level.
zoom1- min-pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual
zoom1- min-pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual

Note: The lens without optocoupler positioning does not need to configure optocoupler parameters.

13.2.5 PIRIS description:

Member name description
use-p-iris Whether to use the function of P-IRIS
piris-used-pin Each ms41908 chip can drive two stepping motors, the corresponding pin groups are called “ab” and “cd”, according to the actual hardware connection configuration
piris-backlash The error caused by the gear gap, the number of steps to be compensated when the motor direction changes, and the data obtained according to the actual lens test
piris-start-up- speed The starting speed of the stepping motor, in PPS
piris-step-max The effective movement range of the motor, the unit is the number of steps
piris-ppw Set ms41908 output pwm duty cycle, 0-255, the larger the value, the stronger the drive capacity, adjust according to the motor load
piris-phmode Set ms41908 output PWM waveform phase correction, generally not configured, it depends on the situation
piris-micro Set the number of microsteps, divided into 64, 128, 256 subdivisions, the default is 256 subdivisions
piris-1-2phase- excitation The default motor excitation mode is 2-2 phase excitation, this parameter can be configured using 1-2 phase excitation ag. piris-1-2phase-excitation;
piris-dir- opposite If the current motor movement direction is opposite to the actual focus curve, this parameter can be configured to reverse the motor movement direction ag. piris-dir-opposite;

Optocoupler description:

Member name description
piris-pic The C pin of the optocoupler is used to detect the level transition. The junction point of the level transition is the origin point of the optocoupler
piris-pia The A pin of the optocoupler drives the photodiode. When the optocoupler is calibrated, it should be pulled up, and it should be pulled down during normal operation, otherwise the photodiode will affect the imaging.
piris-pie When the hardware is designed, it can be directly grounded. If it is designed to be controlled by gpio, it needs to configure the pin to be low level.
piris-min- pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual
piris-min- pos The number of steps on the left and right of the optocoupler origin needs to be measured, and then filled in dts, which can be larger than actual

Note: The lens without optocoupler positioning does not need to configure optocoupler parameters.

13.2.6 DCIRIS description:

Member name description
use-dc-iris Whether to use the function of DC-IRIS
vd_iris-gpios Synchronous pulse pin for DC aperture related registers to take effect
dc-iris-reserved- polarity DC aperture polarity setting, if 0 means the aperture is fully open, you can set this property to reverse
dc-iris-max-log The target value range of the DC iris is 0~1023, the actual effective range may be relatively small, this parameter can be configured to limit the effective range

13.2.7 Brief description of data type

13.2.7.1 struct spi_driver

[Description]

Define platform device driver information

[Definition]

  struct spi_driver {
          int (*probe)(struct spi_device *spi);
          int (*remove)(struct spi_device *spi);
          struct device_driver driver;
          const struct spi_device_id *id_table;
  };

[Key Member]

Member name description
@driver struct device_driver driver mainly contains the name of the driver and of_match_table for matching with DTS registered devices. When the compatible field in of_match_table matches the compatible field in the dts file, the .probe function will be called
@id_table If the kernel does not use of_match_table and dts registered equipment for matching, the kernel uses the table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  static const struct spi_device_id motor_match_id[] = {
      {"relmon,ms41908", 0 },
      { }
  };
  static struct spi_driver motor_dev_driver = {
      .driver = {
          .name = DRIVER_NAME,
          .of_match_table = of_match_ptr(motor_dev_of_match),
      },
      .probe      = &motor_dev_probe,
      .remove     = &motor_dev_remove,
      .id_table   = motor_match_id,
  };
13.2.7.2 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name description
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops motor_core_ops = {
      .ioctl = motor_ioctl,
  };
  static const struct v4l2_subdev_ops motor_subdev_ops = {
      .core   = &motor_core_ops,
  };
13.2.7.3 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
      int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name description
.g_volatile_ctrl Get a new value for this control. Generally only relevantfor volatile (and usually read- only) controls such as a control that returns the current signal strength which changes continuously.
.s_ctrl Actually set the new control value. s_ctrl is compulsory. The ctrl->handler->lock is held when these ops are called, so no one else can access controls owned by that handler.

[Example]

  static const struct v4l2_ctrl_ops motor_ctrl_ops = {
      .s_ctrl = motor_s_ctrl,
  };

13.2.8 API brief description

13.2.8.1 xxxx_set_ctrl

[description]

Call standard v4l2_control to set focus, zoom, P aperture position

The driver implements the following v4l2 standard commands:

Parameter name Description
V4L2_CID_FOCUS_ABSOLUTE Control the focus, 0 means the minimum focal length, clear near
V4L2_CID_ZOOM_ABSOLUTE Control the zoom factor, 0 means the zoom factor is the smallest and the angle of view is the largest
V4L2_CID_IRIS_ABSOLUTE Control the size of the aperture opening, 0 means the aperture is closed
V4L2_CID_ZOOM_CONTINUOUS Control the zoom factor zoom1, used when multiple zoom groups are controlled

[grammar]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer input
13.2.8.2   xxxx_ioctl xxxx_compat_ioctl

[description]

The realization function of custom ioctl mainly includes the time information of obtaining focus, zoom and P aperture (time stamp of start and end movement). Since the lens used does not have a positioning device, it is necessary to reset the position of the lens motor when necessary .

The driver implements custom commands::

Parameter name Description
RK_VIDIOC_VCM_TIMEINFO Focusing time information, used to confirm whether the current frame is the effective frame after focusing
RK_VIDIOC_ZOOM_TIMEINFO Time information of zooming, used to confirm whether the current frame is the effective frame after zooming is completed
RK_VIDIOC_IRIS_TIMEINFO The time information of the aperture, used to confirm whether the current frame is the effective frame after P aperture adjustment
RK_VIDIOC_ZOOM1_TIMEINFO When there are multiple zoom groups, the time information of zoom1 is used to confirm whether the current frame is the effective frame after zooming is completed
RK_VIDIOC_IRIS_CORRECTION Aperture position reset, only works on P-IRIS
RK_VIDIOC_FOCUS_CORRECTION Focus position reset
RK_VIDIOC_ZOOM_CORRECTION Zoom position reset
RK_VIDIOC_ZOOM1_CORRECTION Double zoom lens, the second group of zoom position reset
RK_VIDIOC_FOCUS_SET_POSITION Set the focus position
RK_VIDIOC_ZOOM_SET_POSITION Set the follow focus parameters and realize multi-step zoom and focus linkage according to the zoom curve

Note:

1. In order to solve the problem of the inaccuracy of the absolute position of the motor caused by the gear gap, by fixing one direction as the positive direction and the other as the negative direction, the initial position of the gear is stuck in the positive direction. When the motor goes in the negative direction, it must go more than the gear. The number of clearance steps is n, and then the number of steps in the positive direction is n, so that the gear can remain stuck in the positive direction, which is called callback. The callback ensures the accuracy of the absolute position. However, the number of callback steps is greater than the gear gap. During manual focusing or automatic focusing, if you move in the negative direction for multiple times, the continuous callback will give people the feeling of jitters, so you cannot callback every time you move in the negative direction. The newly added RK_VIDIOC_FOCUS_SET_POSITION and RK_VIDIOC_ZOOM_SET_POSITION interfaces are determined by the af algorithm whether to call back. The standard v4l2 commands V4L2_CID_FOCUS_ABSOLUTE and V4L2_CID_ZOOM_ABSOLUTE do not call back and are only used in manual mode. RK_VIDIOC_ZOOM_SET_POSITION contains focus and zoom parameters. The focus is adjusted synchronously during the zooming process to make the picture excessively natural.

2. In order to solve the gear gap in the early stage, by configuring the focus-backlash, when walking in the negative direction, take more steps of the gear gap to offset the gear gap. However, due to the individual difference of the lens gear gap, there is an error in the calibration and the calibration workload Is large, so this parameter is discarded. The drive retains its design, and it can still be used if the position accuracy of the motor is not high.

[grammar]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
cmd ioctl command input
*arg/arg Parameter pointer output

[return value]

Return value Description
0 Success
Not 0 Failed

13.2.9 Drive migration steps

For SPI controlled driver chips, you can use the SPI framework for device driver migration, MS41908 as a reference. Driver reference: /kernel/drivers/media/spi/ms41908.c

The migration steps are as follows:

1.Implement the standard spi sub-device driver part.

1.1 According to the description of struct spi_driver,the following parts are mainly realized:

struct driver.name

struct driver. of_match_table

probe function

remove function

1.2 Probe function implementation details description:

1) Equipment resource acquisition, mainly to obtain DTS resources, reference MS41908 device registration(DTS);

1.1) RK private resource definition, naming methods such as rockchip, camera-module-xxx, mainly to provide equipment parameters and Camera equipment to match.

1.2) Obtain motor-related configuration parameters, which are defined according to the function requirements of the chip, and try to make the parameters related to motor motion configurable.

2. hrtimer_init,Timer initialization, ms41908 uses the vd signal as the trigger signal. The timer is used to fix the period of each vd, which is convenient for operation. The register of ms41908 takes effect after the vd signal. Every time the register value needs to be modified, it can be advanced before the vd signal. Configuration register. It should be noted that the movement speed and the number of movement steps configured by the register must be within the range of the vd period, and the number of steps that exceed the vd period will be lost.

3)init_completion,The synchronization mechanism is realized through completion. For the same motor, the next operation can only be performed after the previous operation is over.

4. Initialization of v4l2 device and media entity

v4l2 sub-device: v4l2_i2c_subdev_init, the driver requires subdev to have its own device node for user mode rkaiq to access, and realize the control of the motor through this device node;

media entity: media_entity_init;

5. Device name:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           motor->module_index, facing,
           DRIVER_NAME);

2.Implement v4l2 sub-device driver, mainly implement the following 2 members:

  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Refer to v4l2_subdev_core_ops instructions to implement the callback function, mainly implement the following callback functions:

  .ioctl
  .compat_ioctl32

2.2 Refer to v4l2_ctrl_ops instructions to implement the callback function, mainly implement the following callback functions:

.g_volatile_ctrl
.s_ctrl

14. DC-IRIS drive

Compared with P-IRIS, DC-IRIS cannot accurately know the size of the aperture opening. Generally, the scene is fully opened by default. When the exposure is adjusted to the minimum, the image is still overexposed, and then enters the aperture adjustment. When the exposure is set to the maximum, the image is still Under exposure, enter the aperture adjustment. The DC-IRIS motor is a DC motor, which buffers the adjustment speed of the motor through the negative feedback of the Hall device. For the drive, as long as the motor is controlled by a PWM, when the PWM duty cycle is less than 20%, the iris will slowly close until it is completely closed. The smaller the duty cycle, the faster the iris closes; when the duty cycle is greater than The 40% aperture will slowly open, the larger the duty cycle, the faster the opening speed; the aperture in the 20%~40% range is in a hold state. The 20% and 40% here are not fixed values, which are related to the frequency of pwm and the accuracy of the actual hardware devices. Reference driver: /kernel/drivers/media/i2c/hall-dc-motor.c

14.1 DC-IRIS Device Registration (DTS)

  hal_dc_motor: hal_dc_motor{
          status = "okay";
          compatible = "rockchip,hall-dc";
          pwms = <&pwm6 0 2500 0>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
  };
  &pwm6 {
          status = "okay";
          pinctrl-names = "active";
          pinctrl-0 = <&pwm6m0_pins_pull_down>;
  };
  &i2c1 {
      imx334: imx334@1a {
          ...
          lens-focus = <&hal_dc_motor>;
          ...
      }
  }

14.1.1 Brief description of data type

14.1.1.1 struct platform_driver

[Description]

Define platform device driver information

[Definition]

  struct platform_driver {
          int (*probe)(struct platform_device *);
          int (*remove)(struct platform_device *);
          void (*shutdown)(struct platform_device *);
          int (*suspend)(struct platform_device *, pm_message_t state);
          int (*resume)(struct platform_device *);
          struct device_driver driver;
          const struct platform_device_id *id_table;
          bool prevent_deferred_probe;
  };

[Key Member]

Member name Description
@driver struct device_driver driver mainly contains the name of the driver and of_match_table for matching with DTS registered devices. When the compatible field in of_match_table matches the compatible field in the dts file, the .probe function will be called
@id_table If the kernel does not use of_match_table and dts registered equipment for matching, the kernel uses the table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  #if defined(CONFIG_OF)
  static const struct of_device_id motor_dev_of_match[] = {
      { .compatible = "rockchip,hall-dc", },
      {},
  };
  #endif
  static struct platform_driver motor_dev_driver = {
      .driver = {
          .name = DRIVER_NAME,
          .owner = THIS_MODULE,
          .of_match_table = of_match_ptr(motor_dev_of_match),
      },
      .probe = motor_dev_probe,
      .remove = motor_dev_remove,
  };
  module_platform_driver(motor_dev_driver);
14.1.1.2 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name Description
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops motor_core_ops = {
      .ioctl = motor_ioctl,
  };
  static const struct v4l2_subdev_ops motor_subdev_ops = {
      .core   = &motor_core_ops,
  };
14.1.1.3 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name Description
.s_ctrl Actually set the new control value. s_ctrl is compulsory. The ctrl->handler->lock is held when these ops are called, so no one else can access controls owned by that handler.

[Example]

  static const struct v4l2_ctrl_ops motor_ctrl_ops = {
      .s_ctrl = motor_s_ctrl,
  };

14.1.2 API brief description

14.1.2.1 xxxx_set_ctrl

[description]

Call the standard v4l2_control iris position, the DC iris actually cannot know the specific position of the iris, the value set here is the duty ratio of pwm.

The following v4l2 standard commands are implemented:

Parameter name Description
V4L2_CID_IRIS_ABSOLUTE Set the duty cycle of pwm that controls the iris, range (0~100)

[grammar]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
14.1.2.2   xxxx_ioctl xxxx_compat_ioctl

[description]

Currently, there is no private definition to be implemented, and v4l2 framework registration is required to implement empty functions.

[grammar]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
cmd ioctl command input
*arg/arg Parameter pointer Output

[return value]

Return value Description
0 Success
Not 0 Failed

14.1.3 Drive migration steps

Driver reference: /kernel/drivers/media/i2c/hall-dc-motor.c

The migration steps are as follows:

1. Implement the standard platform sub-device driver part.

1.1 According to the description of struct platform_driver, the following parts are mainly realized:

struct driver.name

struct driver. of_match_table

probe function

remove function

1.2 Detailed description of the probe function implementation:

1. Device resource acquisition, mainly to obtain DTS resources, refer to DC-IRIS Device Registration (DTS);

1.1) RK private resource definition, naming methods such as rockchip, camera-module-xxx, mainly to provide equipment parameters and Camera equipment to match. To 1.2) To obtain pwm resources, pay attention to whether the pwm node is enabled.

2. Initialization of v4l2 device and media entity.

v4l2 sub-device: v4l2_i2c_subdev_init, the driver requires subdev to have its own device node for user mode rkaiq to access, and realize the control of the motor through this device node;

media entity: media_entity_init;

3. Flash device name:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           motor->module_index, facing,
           DRIVER_NAME);

2. Implement the v4l2 sub-device driver, which mainly implements the following 2 members:

  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Refer to v4l2_subdev_core_ops to explain the implementation of the callback function, which mainly implements the following callback functions:

  ioctl
  .compat_ioctl32

The callback currently does not need to implement specific commands, but as a sub-device of v4l2, the operation function must be implemented, so an empty function is implemented here.

2.2 Refer to the description of v4l2_ctrl_ops to implement the callback function, which mainly implements the following callback functions:

.g_volatile_ctrl.s_ctrl

.g_volatile_ctrl and .s_ctrl implement the following commands with standard v4l2 control:

Member name Description
V4L2_CID_IRIS_ABSOLUTE Set the duty cycle of pwm that controls the iris, range (0~100)

15. RK-IRCUT driver

The IRCUT is controlled by two wires. A 3.5v~6v power supply is applied to the two wires. The IRCUT can be switched by reversing the positive and negative poles of the IRCUT power supply and meeting the power-on time of 100ms±10%. The driver controls the current output direction of the motor driver through two gpio. The gpio commands are open (red line) and close (black line). The current flows from open to close, which is the infrared cut filter, working during the day; the current flows from close to open, which is a white glass sheet and works at night.

15.1 RK-IRCUT Device Registration (DTS)

  cam_ircut0: cam_ircut {
          status = "okay";
          compatible = "rockchip,ircut";
          ircut-open-gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_HIGH>;
          ircut-close-gpios  = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
  };
  &i2c1 {
      imx334: imx334@1a {
          ...
          ir-cut = <&cam_ircut0>;
          ...
      }
  }

15.1.1 Brief description of data type

15.1.1.1 struct platform_driver

[Description]

Define platform device driver information

[Definition]

  struct platform_driver {
          int (*probe)(struct platform_device *);
          int (*remove)(struct platform_device *);
          void (*shutdown)(struct platform_device *);
          int (*suspend)(struct platform_device *, pm_message_t state);
          int (*resume)(struct platform_device *);
          struct device_driver driver;
          const struct platform_device_id *id_table;
          bool prevent_deferred_probe;
  };

[Key Member]

Member name Description
@driver struct device_driver driver mainly contains the name of the driver and of_match_table for matching with DTS registered devices. When the compatible field in of_match_table matches the compatible field in the dts file, the .probe function will be called
@id_table If the kernel does not use of_match_table and dts registered equipment for matching, the kernel uses the table for matching
@probe Callback for device binding
@remove Callback for device unbinding

[Example]

  #if defined(CONFIG_OF)
  static const struct of_device_id ircut_of_match[] = {
      { .compatible = "rockchip,ircut", },
      {},
  };
  #endif
  static struct platform_driver ircut_driver = {
      .driver = {
          .name = RK_IRCUT_NAME,
          .of_match_table = of_match_ptr(ircut_of_match),
      },
      .probe = ircut_probe,
      .remove = ircut_drv_remove,
  };
  module_platform_driver(ircut_driver);
15.1.1.2 struct v4l2_subdev_core_ops

[Description]

Define core ops callbacks for subdevs.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Key Member]

Member name Description
.ioctl called at the end of ioctl() syscall handler at the V4L2 core.used to provide support for private ioctls used on the driver.
.compat_ioctl32 called when a 32 bits application uses a 64 bits Kernel, in order to fix data passed from/to userspace.in order to fix data passed from/to userspace.

[Example]

  static const struct v4l2_subdev_core_ops ircut_core_ops = {
      .ioctl = ircut_ioctl,
  };
  static const struct v4l2_subdev_ops ircut_subdev_ops = {
      .core   = &ircut_core_ops,
  };
15.1.1.3 struct v4l2_ctrl_ops

[Description]

The control operations that the driver has to provide.

[Definition]

  struct v4l2_ctrl_ops {
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Key Member]

Member name Description
.s_ctrl Actually set the new control value. s_ctrl is compulsory. The ctrl->handler->lock is held when these ops are called, so no one else can access controls owned by that handler.

[Example]

  static const struct v4l2_ctrl_ops ircut_ctrl_ops = {
      .s_ctrl = ircut_s_ctrl,
  };

15.1.2 API brief description

15.1.2.1 xxxx_set_ctrl

[description]

Call standard v4l2_control to switch IRCUT.

The following v4l2 standard commands are implemented:

Parameter name Description
V4L2_CID_BAND_STOP_FILTER 0 is CLOSE state, infrared light can enter; 3 is OPEN state, infrared light cannot enter;

[grammar]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[parameter]

Parameter name Description Input and output
*ctrl v4l2 control structure pointer input

[return value]

Return value Description
0 Success
Not 0 Failed
15.1.2.2   xxxx_ioctl xxxx_compat_ioctl

[description]

Currently, there is no private definition to be implemented, and v4l2 framework registration is required to implement empty functions.

[grammar]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[parameter]

Parameter name Description Input and output
*sd v4l2 subdev structure pointer input
cmd ioctl command input
*arg/arg Parameter pointer Output

[return value]

Return value Description
0 Success
Not 0 Failed

15.1.3 Drive migration steps

Driver reference: /kernel/drivers/media/i2c/rk_ircut.c

The migration steps are as follows:

1. Implement the standard platform sub-device driver part.

1.1 According to the description of struct platform_driver, the following parts are mainly realized:

struct driver.name

struct driver. of_match_table

probe function

remove function

1.2 Detailed description of the probe function implementation:

1. Equipment resource acquisition, mainly to obtain DTS resources, refer to RK-IRCUT Equipment Registration (DTS);

1.1) RK private resource definition, naming methods such as rockchip, camera-module-xxx, mainly to provide equipment parameters and Camera equipment to match.

1.2) Get open and close gpio resources;

2. init_completion, the synchronization mechanism is realized through completion. Since it takes about 100ms to switch the IRCUT, the completion synchronization mechanism is required to ensure that the last IRCUT switch has been completed before the operation can be performed again;

3. Create a work queue and place the switching operation on the work queue to avoid long-term blocking;

4. Initialization of v4l2 device and media entity.

v4l2 sub-device: v4l2_i2c_subdev_init, the driver requires subdev to have its own device node for user-mode rkaiq to access, and control IRCUT through this device node;

media entity: media_entity_init;

  sd->entity.function = MEDIA_ENT_F_LENS;
  sd->entity.flags = 1;//flag is fixed to 1, used to distinguish other sub-devices of MEDIA_ENT_F_LENS type

5. Device name:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           ircut->module_index, facing,
           RK_IRCUT_NAME);

2. Implement the v4l2 sub-device driver, which mainly implements the following 2 members:

  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Refer to v4l2_subdev_core_ops to explain the implementation of the callback function, which mainly implements the following callback functions:

  .ioctl
  .compat_ioctl32

This callback currently does not need to implement private commands, but v4l2 framework registration requires it, so an empty function is implemented, and the content of the function can be supplemented according to needs in the future.

2.2 Refer to the description of v4l2_ctrl_ops to implement the callback function, which mainly implements the following callback functions:

.s_ctrl

.s_ctrl implements the following commands with standard v4l2 control:

Member name Description
V4L2_CID_BAND_STOP_FILTER 0 is CLOSE state, infrared light can enter; 3 is OPEN state, infrared light cannot enter;

16. media-ctl v4l2-ctl tool

The media-ctl tool operates through media devices such as /dev/medio0. It manages the format, size, and link of each node in the Media topology.

The v4l2-ctl tool is for video devices such as /dev/video0 and /dev/video1. It performs a series of operations such as set_fmt, reqbuf, qbuf, dqbuf, stream_on, stream_off, etc. on the video device.

For specific usage, please refer to the help information of the command. The following are some common usages.

1. Print topology

  media-ctl -p -d /dev/media0

Note: There are many device nodes in isp2, and media0/media1/media2 nodes may exist. You need to enumerate and view device information one by one.

2. Link

  media-ctl -l'"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[0]'
  media-ctl -l'"rkisp-isp-subdev":2->"rkisp_mainpath":0[1]'

Note: Disconnect the path of ispp, link to main_path, grab the raw image from main_path, media-ctl does not add -d to specify the device, the default is /dev/media0 device, you need to confirm which device rkisp-isp-subdev is hung on On the node, it is usually /dev/media1.

3. Modify fmt/size

  media-ctl -d /dev/media0 \
  --set-v4l2'"ov5695 7-0036":0[fmt:SBGGR10_1X10/640x480]'

Note: You need to confirm which media device the camera device node (ov5695 7-0036) is mounted on.

4. Set fmt and grab the frame

  v4l2-ctl -d /dev/video0 \
  --set-fmt-video=width=720,height=480,pixelformat=NV12 \
  --stream-mmap=3 \
  --stream-skip=3 \
  --stream-to=/tmp/cif.out \
  --stream-count=1 \
  --stream-poll

5. Set exposure, gain and other controls

  v4l2-ctl -d /dev/video3 --set-ctrl'exposure=1216,analogue_gain=10'

Note: The isp driver will call the control command of the camera sub-device, so the specified device as video3 (main_path or self_path) can be set to exposure, vicap will not call the control command of the camera sub- device, and setting the control command directly on the acquisition node will fail. The correct way is to find the camera device node is /dev/v4l-subdevX and directly configure the terminal node.

17. RV1109/RV1126 Memory Optimization Guide

MIPI -> DDR_1 -> ISP -> DDR_2 -> ISPP(TNR) -> DDR_3 -> ISPP(NR&Sharp) -> DDR_4 -> ISPP(FEC) -> DDR_5

1. DDR_1: Vicap raw data is written to ddr, or isp mipi raw data is written to ddr, and isp reads raw data from ddr for processing

Occupied memory: buf_cnt * buf_size * N, (N = 1: linear mode, 2: hdr2 frame mode 3: hdr3 frame mode).

buf_size: ALIGN(width * bpp / 8, 256) * height; //bpp is the bit width, raw8 raw10 or raw12

buf_cnt: 4 by default, define the aiq library code hwi/isp20/CamHwIsp20.h, 3 at least.

#define ISP_TX_BUF_NUM 4
#define VIPCAP_TX_BUF_NUM 4

config vicap device ROCKCHIP_CIF_USE_NONE_DUMMY_BUF to reduce one internal buf

2. DDR_2: isp fbc yuv420 and gain data are written to ddr, and ispp reads from ddr for processing

Occupied memory: buf_size * buf_cnt

buf_size: ALIGN(width, 64) * ALIGN(height, 128) / 16 + ALIGN(width, 16) * ALIGN(hieght, 16) * 1.5625

buf_cnt: 4 bufs in tnr 3to1 mode, 3 bufs in 2to1 mode, the mode is configured in iq xml

If motion function on, one scale output, mxn downsampling supports 4x8 and 8x8 IQ XML configuration options.

buf_size:ALIGN(width / m, 16) * (height / n) * 1.5

buf_cnt: default 6, depend on AIQ self_path video request buf.

3. DDR_3: ispp tnr fbc yuv420 and gain data written to ddr, ispp NR&Sharp reads and processes from ddr again

Occupied memory: buf_size * buf_cnt

buf_size: ALIGN(width, 64) * ALIGN(height, 128) / 16 + ALIGN(width, 16) * ALIGN(hieght, 16) * 1.5625

buf_cnt: 2, which is the smallest

4. DDR_4: ispp NR&Sharp yuyv data is written to ddr, and ispp fec is read from ddr for processing

Occupied memory: buf_size * buf_cnt (fec function does not open and does not occupy memory)

buf_size: width * height * 2

buf_cnt: 2, which is the smallest

5. DDR_5: ispp 4-channel output image buffer, the buffer size is calculated according to the resolution, format and buf_cnt set by the user

The above buf_cnt is where the memory can be optimally configured

isp cma memory reserved size, can configure more memory and get the actual size after camera app running.

  isp_reserved: isp {
      compatible = "shared-dma-pool";
      inactive;
      reusable;
      size = <0x10000000>;//256M and need 4M align
  };
  enable cma debug
  +++ b/arch/arm/configs/rv1126_defconfig
  @@ -62,6 +62,8 @@ CONFIG_IOSCHED_BFQ=y
   CONFIG_KSM=y
   CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
   CONFIG_CMA=y
  +CONFIG_CMA_DEBUG=y
  +CONFIG_CMA_DEBUGFS=y
  one page is 4K, 26091 page is 104364K and need 4M align, so config 104M to
  isp_reserved
  [root@RV1126_RV1109:/sys/kernel/debug/cma/cma-isp@0]# ls
  alloc  base_pfn  bitmap  count free  maxchunk order_per_bit  used
  [root@RV1126_RV1109:/sys/kernel/debug/cma/cma-isp@0]# cat used
  26091

18. RV1109/RV1126 Delay Optimization Guide

1、config vicap wait-line

config wait-line to vicap node on dts, such as height is 1520, and wait-line is 760, the buffer is output to the isp in advance after half of the image is collected. Adjust the wait-line according to the speed at which the isp reads the buffer.

&rkcif_mipi_lvds {
wait-line = <760>;
};

It can also be configured by the following command, which supports dynamic configuration

  echo 1000 > /sys/devices/platform/rkcif_mipi_lvds/wait_line

Note: The wait-line configuration is too small, the isp accesses the buffer memory too early, and some data has not yet been collected. The part of the buffer that has not collected data is buffered by the previous image. When the screen changes drastically, the end of the image will be abnormal, showing a split state. You need to select the appropriate wait-line based on the actual test.

2、config isp wait-line

config wait-line to isp node on dts, such as height is 1520, and wait-line is 760, that the image is processed to line 760 output to ispp. Adjust the wait-line according to the ISP processing time and ISPP processing time.

&rkisp_vir0 {
wait-line = <760>;
};

Also config /sys/module/video_rkisp/parameters/wait_line to debug,config it before isp video open。

NOTE: The wait-line configuration is too small, and ISPP processing speed is faster than ISP, due to the use of FBC compression format, hold situation occurs. Motion function and multi-sensor not support this.

3、config ispp wait-line for four streams output

config wait-line to ispp node on dts, such as height is 1520, and wait-line is 896, that the image is processed to line 896 output to the backend. Adjust the wait-line according to the ISPP processing time (nr or fec) and the backend processing time.

&rkispp_vir0 {
     status = "okay";
     wait-line = <896>;
};

Also config /sys/module/video_rkispp/parameters/wait_line to debug,config it before ispp video open。

Note: The wait-line configuration is too small, and the back-end processing speed is faster than ISPP, the back- end image processing will be abnormal. The multi-sensor not supported.

4、Improve hardware processing speed

1)Improve isp/ispp clk

drivers/media/platform/rockchip/isp/hw.c

static const struct isp_clk_info rv1126_isp_clk_rate[] = {
{
.clk_rate = 20,
.refer_data = 0,
}, {
.clk_rate = 600,
.refer_data = 1920, //width
}, {
.clk_rate = 600,
.refer_data = 2688,
}, {
.clk_rate = 600,
.refer_data = 3072,
}, {
.clk_rate = 600,
.refer_data = 3840,
}
};

drivers/media/platform/rockchip/ispp/hw.c

static const struct ispp_clk_info rv1126_ispp_clk_rate[] = {
{
.clk_rate = 150,
.refer_data = 0,
}, {
.clk_rate = 500,
.refer_data = 1920 //width
}, {
.clk_rate = 500,
.refer_data = 2688,
}, {
.clk_rate = 500,
.refer_data = 3072,
}, {
.clk_rate = 500,
.refer_data = 3840,
}
};

2)Disable iommu and using memory reserved

&rkisp_mmu {
status = "disabled";
};
  &rkisp {
        memory-region = <&isp_reserved>;
  };
&rkispp_mmu {
status = "disabled";   };
  &rkispp {
        memory-region = <&isp_reserved>;
  };

19. FAQ

19.1 How to update the driver version separately

1.format new sdk kernel patch

git format-patch A..B drivers/media/common drivers/media/v4l2-core drivers/media/platform/rockchip drivers/media/i2c include/uapi/linux/rkisp2-config.h include/uapi/linux/rkisp21-config.h include/uapi/linux/rkispp-config.h include/uapi/linux/rkcif-config.h include/uapi/linux/rk-camera-module.h include/uapi/linux/rk_vcm_head.h include/uapi/linux/videodev2.h include/uapi/linux/media-bus-format.h -o tmp_patch

2.add patch to old sdk kernel

git am tmp_patch/*

NOTE:A is old kernel commit id,B is new kernel commit id,tmp_patch is output patches。

19.2 How to get the driver version number

Obtained from the kernel startup log

  rkisp ffb50000.rkisp: rkisp driver version: v00.01.00
  rkispp ffb60000.rkispp: rkispp driver version: v00.01.00

Obtained by

  cat /sys/module/video_rkisp/parameters/version
  cat /sys/module/video_rkispp/parameters/version

19.3 How to judge the RKISP driver loading status

If the RKISP driver is successfully loaded, video and media devices will exist in the /dev/ directory. There may be multiple /dev/video devices in the system, and the video node registered by RKISP can be queried through /sys.

  localhost ~ # grep'' /sys/class/video4linux/video*/name

You can also use the media-ctl command to print the topology to check whether the pipeline is normal.

Determine whether the camera driver is loaded successfully. When all cameras are registered, the kernel will print out the following log.

  localhost ~ # dmesg | grep Async
  [0.682982] RKISP: Async subdev notifier completed

If you find that the kernel does not have the Async subdev notifier completed line of log, please first check whether the sensor has related errors and whether the I2C communication is successful.

19.4 How to configure ISP/VICAP RAW storage format

isp:

rv1109/rv1126:

Three mode:

0: raw12/raw10/raw8 8bit memory compact

1: raw12/raw10 16bit memory one pixel big endian

|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
| 3| 2| 1| 0| -| -| -| -|11|10| 9| 8| 7| 6| 5| 4|

2: raw12/raw10 16bit memory one pixel big align

|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| -| -| -| -|

rk356x:

Three mode:

0: raw12/raw10/raw8 8bit memory compact

1: raw12/raw10 16bit memory one pixel little align

|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
| -| -| -| -|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|

2: raw12/raw10 16bit memory one pixel big align

|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| -| -| -| -|

Control instructions:

aiq increases the control of the storage mode, starting the aiq program will configure the supported storage mode according to the sensor model.

rv1109/rv1126: Support for aiq version v0x1.0x71.1 and above rk356x:Support for aiq version v2.60.01 and above

Users can also control the storage format by executing ioctl on the streaming device. There are related definitions in include/uapi/linux/rkisp2-config.h:

  #define RKISP_CMD_GET_CSI_MEMORY_MODE \
      _IOR('V', BASE_VIDIOC_PRIVATE + 100, int)
  #define RKISP_CMD_SET_CSI_MEMORY_MODE \
      _IOW('V', BASE_VIDIOC_PRIVATE + 101, int)
  enum isp_csi_memory {
      CSI_MEM_COMPACT = 0,
      CSI_MEM_WORD_BIG_END = 1,
      CSI_MEM_WORD_LITTLE_ALIGN = 1,
      CSI_MEM_WORD_BIG_ALIGN = 2,
  };

vicap:

rv1109/rv1126/rk356x:

Three mode:

0: raw12/raw10/raw8 8bit memory compact

1: raw12/raw10 16bit memory one pixel low align for rv1126/rv1109/rk356x

|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
| -| -| -| -|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|

2: raw12/raw10 16bit memory one pixel high align for rv1126/rv1109/rk356x

|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| -| -| -| -|

note: rv1109/rv1126/rk356x dvp only support uncompact mode, and can be set low align or high align

Control instructions:

aiq increases the control of the storage mode, starting the aiq program will configure the supported storage mode according to the sensor model.

rv1109/rv1126: Support for aiq version v0x1.0x71.1 and above rk356x:Support for aiq version v2.60.01 and above

Users can also control the storage format by executing ioctl on the streaming device. There are related definitions in include/uapi/linux/rkcif-config.h:

  #define RKCIF_CMD_GET_CSI_MEMORY_MODE \
      _IOR('V', BASE_VIDIOC_PRIVATE + 0, int)
  #define RKCIF_CMD_SET_CSI_MEMORY_MODE \
      _IOW('V', BASE_VIDIOC_PRIVATE + 1, int)
  enum cif_csi_lvds_memory {
      CSI_LVDS_MEM_COMPACT = 0,
      CSI_LVDS_MEM_WORD_LOW_ALIGN = 1,
      CSI_LVDS_MEM_WORD_HIGH_ALIGN = 2,
  };

For vicap, it can be configured by the following command, but it is only used for debugging

Configured as non-compact, each number corresponds to a channel

  echo 0 0 0 0 > /sys/devices/platform/rkcif_mipi_lvds/compact_test

Configured for low alignment

  echo 0 0 0 0 > /sys/devices/platform/rkcif_mipi_lvds/is_high_align

Configured for high alignment

  echo 0 0 0 0 > /sys/devices/platform/rkcif_mipi_lvds/is_high_align

19.5 How to configure VICAP abnormal reset

The vicap driver has a reset mechanism, which is used to perform cru reset operation on vicap when an abnormal situation occurs in vicap. The specific usage is as follows:

The configuration method for kernel-4.19 is as follows:

To start the reset mechanism, you need to add rockchip and cif-monitor parameters to the cif-related interface device node on the dts. If the dts does not set this parameter, the reset mechanism is not enabled by default.

  &rkcif_mipi_lvds {
      status = "okay";
      /* rockchip,cif-monitor = <index0 index1 index2 index3 index4>; */
      rockchip,cif-monitor = <2 2 5 1000 5>;
      port {
          /* MIPI CSI-2 endpoint */
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1 2 3 4>;
          };
      };
  };

index0: used to describe the reset mode, currently there are four main modes, the status is as follows:

mode directions
Idle not to used monitor
Continue It is used for real-time continuous monitoring of vicap whether mipi error and current interruption. When an error or interruption occurs, the vicap reset is performed; the monitoring timer is initialized at the end of the frame when the number of frames set by index1 arrives, and then starts monitoring. When the corresponding frame number is reached, the monitoring cannot be triggered; the timer performs sampling and detection at the period set by index2;
Trigger The reset is triggered only when a mipi error at the csi2 protocol level occurs in vicap. Set the number of mipi error reports by index4. When the number of index4 is reached, the initialization of the monitoring timer will be interrupted at the end of the frame. After the period set by the index2 parameter is reached, a vicap reset will be realized;
Hotplug The hot plug mode is mainly implemented for car-machine adapter chips like n4/tp6188, which is used to solve the problem of image fragmentation or cut-off when plugging and unplugging; this mode has the function of continue mode, that is, real-time continuous monitoring of vicap Mipi error and cut-off, vicap reset when an error or cut-off occurs; the monitoring timer is initialized at the end of the frame when the number of frames set by index1 arrives, and then starts monitoring. If the corresponding frame number is not reached, it cannot Trigger monitoring; the timer performs sampling detection at the period set by index2; the difference with continue is that if mipi does not report an error and continues to flow, if the sensor collected by vicap is reset and enabled by the RKMODULE_SET_VICAP_RST_INFO command, then vicap is in After obtaining this information through RKMODULE_GET_VICAP_RST_INFO, the reset operation will be triggered.

index1: For continue or hotplug, after collecting index1 frame, start the monitoring timer;

Index2: The period of the monitoring timer, with a frame as the unit, and the monitoring period is index2 frame;

Index3: Time parameter for delayed reset. After the vicap csi2 error is found, the monitoring is continued within the defined time. When the error is detected and no more increases, reset is performed. After the defined time, regardless of whether the error is still increasing, the reset operation is performed immediately. The time unit is ms;

Index4: used to set the number of occurrences of mipi csi err, after reaching this number, trigger reset;

In order to support anomaly detection in both mipi and dvp, the anomaly detection mechanism has been modified and needs to be updated to include the following submissions:

  media: rockchip: rkcif reset all dev when trigger reset event
      move monitor param to rkcif node
      ag &rkcif {
          status = "okay";
          rockchip,cif-monitor = <3 200 1000 5 0>;
          /*
           * index 0: monitor mode
           *     val: 0 idle
           *          1 Continue mode, detect cut of stream or csi2 err
           *          2 trigger mode, detect csi2 err
           *          3 Hotplug, detect hot plug or cut off stream or csi2 err
           * index 1: monitor cycle
           *     val: timer of monitor cycle, unit ms
           * index 2: error interval
           *     val: time of error keeping, such as 1000,
           *          mean atfer one second error still occur,force reset dev,
           *          the max timer to wait error stop
           * index 3: err_ref_cnt:
           *     val: timer error ref val for reset
           * index 4: reset_by_user
           *     val: set val 1 to control reset by user
           */
      };
      Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
      Change-Id: If4da872c7ee3c5140f94e5cf331cab84005361d2

detail: 1) “rockchip, cif monitor” configuration from rkcif_ mipi_lvds moved to the rkcif node 2) Delete the index1, Instead, start detection after starting the stream 3) Add parameter of reset_by_user , set to 1, indicates that the driver does not actively reset and waits for the application to reset. The application regularly trains the video node’s ioctl “RKCIF_CMD_ET_RESET_INFO” to obtain the reset status. When the status is 1, it indicates that a reset is needed. The application can call the ioctl “RKCIF_CMD_SET_RESET” at the appropriate time to execute the reset action.

The configuration method for kernel-5.10 is as follows:

drivers/media/rockchip/cif/Kconfig adds configuration for anomaly detection, which can be directly modified to default values or added to defconfig to override default values. The specific parameters are as follows:

ROCKCHIP_CIF_USE_MONITOR Whether to enable anomaly monitoring mechanism, it needs to be enabled by the customer and is disabled by default
ROCKCHIP_CIF_MONITOR_MODE The mode of anomaly monitoring, defined in accordance with kernel 4.19
ROCKCHIP_CIF_MONITOR_START_FRAME From which frame to start detection, it is recommended to configure it to 0
ROCKCHIP_CIF_MONITOR_CYCLE Detection cycle, measured in frame intervals. When the frame rate is 25fps and configured as 4, the detection cycle is 40ms * 4. Based on the project evaluation, it is recommended to have a detection cycle of around 400ms
ROCKCHIP_CIF_MONITOR_KEEP_TIME The time parameter for delayed reset. After discovering an error in vicap csi2, continuous monitoring is carried out within the defined time. When the error is detected and no longer increases, a reset is performed. After the defined time, regardless of whether the error is still increasing, a reset operation is immediately performed. The parameter unit is ms
ROCKCHIP_CIF_MONITOR_ERR_CNT Generally refers to the number of MIPI error statistics, with a default configuration of 5, indicating that a reset is triggered after counting 5 * 2 errors
ROCKCHIP_CIF_RESET_BY_USER When configured to 1, it means only detecting anomalies and not actively resetting, notifying the application to reset at the appropriate time.

If it is a user controlled reset, the following two points need to be noted: 1)The reset event is passed through the mipi csi2 node, and the corresponding node is found through media ctl - p - d/dev/mediaX (X refers to 0,1,2,3, etc.) to listen for the reset event; 2)Open the video node,stream_cif_mipi_id0~3 can be selected as any one, and these nodes all belong to the same hardware, usually stream_cif_mipi_id0, set the reset ioctl to do the reset operation;

demo:

  #include <stdio.h>
  #include <stdlib.h>
  #include <getopt.h>
  #include <fcntl.h>
  #include <unistd.h>
  #include <sys/ioctl.h>
  #include <linux/videodev2.h>
  #include "rkcif-config.h"
  int subscribe_event(int fd, int event)
  {
      int ret = 0;
      struct v4l2_event_subscription sub;
      if (fd < 0) {
          printf("fd is err\n");
          return -1;
      }
      sub.type = event;
      sub.id = 0;
      ret = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
      if (ret < 0) {
          printf("VIDIOC_SUBSCRIBE_EVENT fail\n");
          return -1;
      }
      return 0;
  }
  int unsubscribe_event(int fd, int event)
  {
      int ret = 0;
      struct v4l2_event_subscription sub;
      if (fd < 0) {
          printf("fd is err\n");
          return -1;
      }
      sub.type = event;
      sub.id = 0;
      ret = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
      if (ret < 0) {
          printf("VIDIOC_SUBSCRIBE_EVENT fail\n");
          return -1;
      }
      return 0;
  }
  int main(int argc, char **argv)
  {
      char *dev;
      int ret;
      int fd = -1;
      int fd_cif = -1;
      int i = 0;
      struct v4l2_event event;
      char *dev_cif;
      if (argc != 3) {
          printf("invalid input\n");
          for (i = 0; i < argc; i++)
              printf("argv[%d]:%s\n", i, argv[i]);
          return -1;
      }
      dev = argv[1];
      fd = open(dev, O_RDWR, 0);
      if (fd < 0) {
          printf("open dev:%s fail\n", dev);
          return -1;
      }
      dev_cif = argv[2];
      fd_cif = open(dev_cif, O_RDWR, 0);
      if (fd_cif < 0) {
          printf("open dev:%s fail\n", dev_cif);
          return -1;
      }
      ret = subscribe_event(fd, V4L2_EVENT_RESET_DEV);
      if (ret < 0)
          goto end;
      while (1) {
              printf("VIDIOC_DQEVENT ready %d\n", ret);
          ret = ioctl(fd, VIDIOC_DQEVENT, &event);
              if (ret) {
                      printf("VIDIOC_DQEVENT err %d\n", ret);
                      goto end;
                 }
          printf("VIDIOC_DQEVENT event %x, %d\n", event.type, event.reserved[0]);
          if (event.type == V4L2_EVENT_RESET_DEV) {
              ret = ioctl(fd_cif, RKCIF_CMD_SET_RESET, &event.reserved[0]);
              if (ret) {
                          printf("RKCIF_CMD_SET_RESET err %d\n", ret);
                          goto end;
              }
                 }
      }
  end:
      ret = unsubscribe_event(fd, V4L2_EVENT_RESET_DEV);
      close(fd);
      close(fd_cif);
      return 0;
  }

19.6 How to capture RAW and YUV data output by CIS

After the driver development is completed, you can directly operate the driver through the standard v4l2-ctl command to obtain the output data of the CIS. You can refer to the v4l2-ctl usage help:https://www.mankier.co m/1/v4l2-ctl

Example:

  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2

-d:Specify the device name

–set-fmt-video:Set the resolution, which must be consistent with the output resolution of the sensor. The current resolution of the sensor can be viewed through media-ctl -p -d /dev/mediaX.

pixelformat:Output data format,such as BG12、NV12.

–stream-mmap:mmap buffer number.

–stream-count:The number of captured frames, multiple frames also exist in the same file.

–stream-to:Specify the storage path.

–stream-skip:The number of frames skipped.

19.6.1 List of equipment support

19.6.1.1 RV1109/RV1126
device interface format Device node name Output Raw Output YUV
VICAP DVP RAW video0~video3 Non-compact Raw no
VICAP MIPI/LVDS RAW video0~video3 Non-compact Raw Compact Raw no
VICAP DVP / MIPI / LVDS YUV video0~video3 no nv12 nv16
ISP DVP / MIPI / LVDS RAW rkisp_rawwr0 rkisp_rawwr1 rkisp_rawwr2 rkisp_rawwr3 Non-compact Raw Compact Raw no
ISP MIPI / LVDS YUV rkisp_mainpath Non-compact Raw nv12 nv16
ISPP Read ddr only YUV rkispp_m_bypass rkispp_scale0 rkispp_scale1 rkispp_scale2 no nv12 nv16
19.6.1.2 RK356X
device interface format Device node name Output Raw Output YUV
VICAP DVP RAW video0~video3 Non-compact Raw no
VICAP MIPI/LVDS RAW video0~video3 Non-compact Raw Compact Raw no
VICAP DVP / MIPI / LVDS YUV video0~video3 no nv12 nv16
ISP DVP / MIPI / LVDS RAW rkisp_rawwr0 rkisp_rawwr1 rkisp_rawwr2 rkisp_rawwr3 Non-compact Raw Compact Raw no
ISP MIPI / LVDS YUV rkisp_mainpath Non-compact Raw nv12 nv16

Note:

1. Device node name query command: media-ctl -p -d /dev/mediaX (X refers to 0, 1, 2, 3…)

19.6.2 Raw data storage format

19.6.2.1 Non-compact storage format RAW

Non-compact type refers to storing raw10 and raw12 data output by the sensor in 16 bits, aligned with high bits. Regarding the storage arrangement of raw12 data in the memory, taking a 4-byte memory segment as an example, the data storage method is as follows:

Non-compact RAW memory layout — original English figure, PDF page 207

Non-compact RAW memory layout — original English figure, PDF page 207

19.6.2.2 Compact storage format RAW

Regarding the storage arrangement of raw12 data in the memory, taking a 4-byte memory segment as an example, the data storage method is as follows:

Compact RAW memory layout — original English figure, PDF page 207

Compact RAW memory layout — original English figure, PDF page 207

Important reminder:

ISP mainpath device, when the input data is Raw10, Raw12, the unified output is the non-compact storage format RAW of Raw12

19.6.3 Reference use case:

19.6.3.1 VICAP output Raw

1、The default value is compact. You can switch between compact and non-compact formats by using the following commands::

      echo 0 > /sys/devices/platform/rkcif_mipi_lvds/compact_test

Among them, 0 means non-compact type, 1 means compact type; for devices that use multiple channels at the same time, the command can be modified to:

      echo 0 0 0 0 > /sys/devices/platform/rkcif_mipi_lvds/compact_test

the numbers after echo correspond to the data storage types of channels vc0, vc1, vc2, and vc3 in turn.

2、 video0~3 correspond to vc0~vc3.

3、v4l2-ctl command

  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2
19.6.3.2 ISP maipath output non-compact Raw

1、You need to capture the image of the mainpath. The default output link of the isp is rkisp-bridge-ispp. You need to switch to the mainpath according to the following command:

      media-ctl -l '"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[0]'
      media-ctl -l '"rkisp-isp-subdev":2->"rkisp_mainpath":0[1]'

Note: If -d is not used, the media0 node is used by default. If rkisp-isp-subdev is not in media0, you need to specify -d to the media node where it is located.

The 0 behind “rkisp-bridge-ispp” means pad0, sink, and detailed instructions to consult v4l2 related documents.

2、isp output format默认是YUYV8_2X8,使用如下命令切换到bayer raw格式:

      media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":2[fmt:SBGGR12_1X12/2688x1520]'

Note: The rkisp-isp-subdev node is not necessarily in media0, -d specifies the device, you need to confirm which media node rkisp-isp-subdev is in.

The 2 behind “rkisp-isp-subdev” means pad2, source, for detailed instructions, please refer to v4l2 related documents.

After the modification, you must use media-ctl -p -d /dev/mediaX (X=0,1,2,…) to check whether the modification takes effect, and the raw data captured after it takes effect is the original raw data.

3、v4l2-ctl command

  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2
19.6.3.3 VICAP output YUV:

Only the input data is in YUV format. If the input is in RAW format, vicap cannot output YUV format.

  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=NV12 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2
19.6.3.4 ISP output YUV:
  v4l2-ctl -d /dev/video5  --set-fmt-video=width=1920,height=1080,pixelformat=NV12 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2

Note:

1. For isp, you can grab mainpath or selfpath, video5 is just an example, please set according to actual parameters. 2. When the ISP input data is Raw, the ISP can convert the Raw data into YUV data, which also includes various image processing operations. Such image processing operations require RK AIQ to control the various image processing modules of the ISP. The current commands are only In the data flow part, the image processing module parameters adopt the driver default values, and the image effect is generally in an abnormal state.

19.6.3.5 ISPP output YUV:

The ispp input data source rkisp-bridge-ispp;

rkisp_mainpath, rkisp_selfpath and rkispp_input_image link need to be closed.

rkisp-isp-subdev pad2: Source format must be fmt:YUYV8_2X8,

isp is linked to ispp by default, the reference command is as follows,

  media-ctl -l '"rkisp-isp-subdev":2->"rkisp_mainpath":0[0]'
  media-ctl -l '"rkisp-isp-subdev":2->"rkisp_selfpath":0[0]'
  media-ctl -l '"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[1]'
  media-ctl -d /dev/media1 -l '"rkispp_input_image":0->"rkispp-subdev":0[1]'
  v4l2-ctl -d /dev/video13 \
  --set-fmt-video=width=2688,height=1520,pixelformat=NV12 \
  --stream-mmap=3 --stream-to=/tmp/nv12.out --stream-count=20 --stram-poll

Note: The -d device name can select the following nodes according to the requirements of the screenshot, and the corresponding node names can be viewed through media-ctl -p -d /dev/mediaX.

rkispp_m_bypass Full resolution and yuv format
rkispp_scale0 Full or scale resolution and yuv formatScale range:[1 8] ratio, 3264 max width
rkispp_scale1 Full or scale resolution and yuv formatScale range:[2 8] ratio, 1280 max width
rkispp_scale2 Full or scale resolution and yuv formatScale range:[2 8] ratio, 1280 max width

19.7 How to switch CIS driver output resolution

1、For the sensor driver that supports multiple resolutions, when you need to capture the raw data of another resolution, you can switch the resolution currently used by the sensor with the following command:

  media-ctl -d /dev/media0 --set-v4l2 '"m01_f_os04a10 1-0036-1":0[fmt:SBGGR12_1X12/2688x1520]'

Note: m01_f_os04a10 1-0036-1 is the name of the sensor node, followed by the required format, provided that the format configuration is supported in the sensor driver

2、For vicap, you only need to set the sensor node, and for the isp, you also need to set the input and output format of the isp. The reference command is as follows:

  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":0[fmt:SBGGR12_1X12/2688x1520]'
  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":0[crop:(0,0)/2688x1520]'
  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":2[fmt:SBGGR12_1X12/2688x1520]'
  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":2[crop:(0,0)/2688x1520]'

19.8 How to set the exposure parameters of CIS

1、Find the sensor node name through media-ctl -p -d /dev/mediaX, the format of the node name is /dev/v4l- subdevX, the reference command is as follows:

  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl 'exposure=1216,analogue_gain=10'

Can also be set separately:

  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl exposure=1216
  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl analogue_gain=10

2、The maximum exposure is limited by sensor vts. The maximum limit may be vts-4 or vts-10. Different sensors are restricted according to the sensor manual. Assuming that the current frame rate is 30fps and the maximum exposure time is 33.3ms, if you want to set the exposure of 40ms, you have to increase the vts to set the exposure of 40ms. It can be converted proportionally, vts_30fps * 30fps = vts_25fps * 25fps, so as to convert the corresponding 25fps vts, (vts-height) is vblank, set the converted vblank to the sensor driver to set a larger exposure, the command reference is as follows:

vts is the frame length, including valid lines and blanking lines

  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl vertical_blanking=200

19.9 How to support black and white cameras

The CIS driver needs to change the output format of the black and white sensor to one of the following three formats.

  MEDIA_BUS_FMT_Y8_1X8 (sensor 8bit output)
  MEDIA_BUS_FMT_Y10_1X10 (sensor 10bit output)
  MEDIA_BUS_FMT_Y12_1X12 (sensor 12bit output)

That is, the above format is returned in the functions xxxx_get_fmt and xxxx_enum_mbus_code.

RKISP driver will make special settings for these three formats to support the acquisition of black and white images.

In addition, if the application layer needs to obtain images in Y8 format, SP Path can only be used, because only SP Path can support Y8 format output.

19.10 How to support odd and even field synthesis

RKISP driver supports odd and even field synthesis function, restriction requirements:

1. MIPI interface: Support output frame count number (from frame start and frame end short packets), RKISP driver uses this to judge the parity of the current field;

2. BT656 interface: support the output standard SAV/EAV, that is, bit6 is the odd and even field flag information, and the RKISP driver uses this to determine the parity of the current field;

3. The RKISP1_selfpath video device node in the RKISP driver has this function, but other video device nodes do not have this function. If the app layer calls other device nodes by mistake, the driver prompts the following error message:

"Only selfpath support interlaced"

RKISP_selfpath information can be viewed with media-ctl -p:

  entity 3: rkisp_selfpath (1 pad, 1 link)
       type Node subtype V4L flags 0
        device node name /dev/video1
      pad0: Sink
         <- "rkisp-isp-subdev":2 [ENABLED]

The device driver is implemented as follows:

The device driver format.field needs to be set to V4L2_FIELD_INTERLACED, which means that the output format of the current device is an odd and even field, that is, the format.field format is returned in the function xxxx_get_fmt. Can refer to driver/media/i2c/tc35874x.c driver;

19.11 How to view debug information

1. Check the media pipeline information, this corresponds to the dts camera configuration

  media-ctl -p -d /dev/mediaX (X = 0, 1, 2 ..)

2. View the proc information, this is the pre-isp/ispp single state and frame input and output information, you can cat several times

  cat /proc/rkisp*

3. View the driver debug information, set the debug level to isp and ispp nodes, the larger the level value, the more information

  echo n> /sys/module/video_rkisp/parameters/debug (n = 0, 1, 2, 3; 0 is off)
  echo n> /sys/module/video_rkispp/parameters/debug
  echo 8 > /proc/sys/kernel/printk

4. Check the register information and pull out reg file

For RV1109/RV1126

      io -4 -l 0x10000 0xffb50000> /tmp/isp.reg
      io -4 -l 0x1000 0xffb60000> /tmp/ispp.reg

For RK3566/RK3568

      io -4 -l 0x10000 0xfdff0000> /tmp/isp.reg

5. Steps to provide debug information

1. Problem site 1->2->4->3

2. Reproduce the problem 3->Start->Reproduce->1->2->4

6, proc information description

  [root@RV1126_RV1109:/]# cat /proc/rkisp*
  rkisp-vir0 Version:v01.06.00
  clk_isp    400000000
  aclk_isp   500000000
  hclk_isp   250000000
  Interrupt  Cnt:7521 ErrCnt:0
  Input      rkcif_mipi_lvds Format:SBGGR10_1X10 Size:2688x1520@30fps Offset(0,0)
  Isp Read   mode:frame2 (frame:1522 rate:33ms idle time:10ms) cnt(total:1522
  X1:1503 X2:18 X3:-1)
  Output     rkispp0 Format:FBC420 Size:2688x1520 (frame:1522 rate:32ms)
  DPCC0      ON(0x5)
  DPCC1      ON(0x5)
  DPCC2      ON(0x5)
  BLS        ON(0x1)
  SDG        OFF(0x80446197)
  LSC        ON(0x1)
  AWBGAIN    ON(0x80446197) (gain: 0x01110111, 0x028a0202)
  DEBAYER    ON(0x7000111)
  CCM        ON(0x80000001)
  GAMMA_OUT  ON(0x80000001)
  CPROC      ON(0xf)
  IE         OFF(0x0) (effect: BLACKWHITE)
  WDR        OFF(0x30cf0)
  HDRTMO     ON(0xa4f05a27)
  HDRMGE     ON(0x80000005)
  RAWNR      ON(0x80100001)
  GIC        OFF(0x0)
  DHAZ       ON(0x80101119)
  3DLUT      OFF(0x2)
  GAIN       ON(0x80010111)
  LDCH       OFF(0x0)
  CSM        FULL(0x80446197)
  SIAF       OFF(0x0)
  SIAWB      OFF(0x0)
  YUVAE      ON(0x400100f3)
  SIHST      ON(0x38000107)
  RAWAF      ON(0x7)
  RAWAWB     ON(0x776887)
  RAWAE0     ON(0x40000003)
  RAWAE1     ON(0x400000f5)
  RAWAE2     ON(0x400000f5)
  RAWAE3     ON(0x400000f5)
  RAWHIST0   ON(0x40000501)
  RAWHIST1   ON(0x60000501)
  RAWHIST2   ON(0x60000501)
  RAWHIST3   ON(0x60000501)
  Monitor    OFF Cnt:0

clk_isp: isp clock frequency

Interrupt: Includes the mipi interrupt, the interrupt of each module in the isp, the data is incremented, indicating that there is data into the isp, ErrCnt error interrupt statistics information

Input: Input source, input format, resolution and crop information

Isp read: mode: one or hdr2/3, frame: sequence number, rate: frame interval, idle/working: isp work state, time: isp hardware working time, cnt: read back number of total, of one time, of two times, of three times

Output: Output object, output format, resolution, frame: sequence number, rate: frame interval

Other: Switch status of each module of isp

Monitor: anomaly detection and reset

  [root@RV1126_RV1109:/]# cat /proc/rkisp*
  rkispp-vir0 Version:v01.06.00
  clk_ispp   350000000
  aclk_ispp  500000000
  hclk_ispp  250000000
  Interrupt  Cnt:79532 ErrCnt:0
  Input      rkisp0 Format:FBC420 Size:2688x1520 (frame:26510 rate:32ms delay:13ms)
  Output     rkispp_m_bypass Format:NV12 Size:2688x1520 (frame:26509 rate:32ms
  delay:30ms)
  TNR        ON(0xf00000f) (mode: 3to1) (global gain: disable) (frame:26510
  time:8ms idle) CNT:0x0 STATE:0x1e000000
  NR         ON(0x57) (external gain: enable) (frame:26510 time:6ms working)
  0x5f0:0x19 0x5f4:0x780f
  SHARP      ON(0x19) (YNR input filter: ON) (local ratio: OFF) 0x630:0x19
  FEC        OFF(0x2) (frame:0 time:0ms idle) 0xc90:0x0
  ORB        OFF(0x0)
  Monitor    ON Cnt:0

clk_ispp: ispp clock frequency

Interrupt: Processing interruption in ispp, data increment indicates that there is data entering ispp, ErrCnt error interruption statistics

Input: Input source, input format, resolution, frame: sequence number, rate: frame interval, delay: input frame time - mipi frame time

Output: Output object, output format, resolution, frame: sequence number, rate: frame interval, delay: output frame time - mipi frame time, also relate to output frame buffer

Other: Switch status of each module of ispp, frame: sequence number, time: module hardware working time, idle/working: module work state

Monitor: anomaly detection and reset

  [root@RV1126_RV1109:/]# cat /proc/rkcif_mipi_lvds
  Driver Version:v00.01.0a
  Work Mode:ping pong
  Monitor Mode:idle
  aclk_cif:500000000
  hclk_cif:250000000
  dclk_cif:297000000
  Input Info:
          src subdev:m01_f_os04a10 1-0036-1
          interface:mipi csi2
          lanes:4
          vc channel: 0 1
          hdr mode: hdr_x2
          format:SBGGR10_1X10/2688x1520@30
          crop.bounds:(0, 0)/2688x1520
  Output Info:
          format:BG10/2688x1520(0,0)
          compact:enable
          frame amount:264
          early:10 ms
          single readout:30 ms
          total readout:30 ms
          rate:33 ms
          fps:30
          irq statistics:
                          total:515
                          csi over flow:0
                          csi bandwidth lack:0
                          all err count:0
                          frame dma end:515

Work Mode: After rv1109, ping pong is used by default, and ping pong mode is recommended.

Monitor Mode: Monitor mode. After the monitor mode is turned on, if mipi detects an abnormality, reset the vicap.

Input Info: Summary of input information

src subdev: Input device, generally refers to sensor device, including camera orientation, index number, device name, i2c bus, 7bit slave address and other information

interface: Data physical interface, mipi, lvds, dvp, etc.

vc channel: The vc channel actually used refers to the virtual channel of multi-channel transmission on the mipi protocol.

hdr mode: The working mode of sensor is divided into normal, hdr_x2, hdr_x3.

format: Input data type

crop.bounds:The trimming parameters can be configured in the sensor driver .get_selection, so as to appropriately trim the data of the input source.

Output Info: Summary of output information

format: Output data type

compact: The default compact output, please refer to the following chapters for related definitions: How to capture RAW and YUV data output by CIS

frame amount:

early: In the wake up mode, after the wait_line line data is collected, the buffer is sent to the isp for processing in advance. The default mode is to send the isp for processing after the complete frame is collected. Early is the optimized time for the isp to be sent to the buffer before the complete frame is collected. Wake up mode configuration instructions are in:RV1109/RV1126 Delay Optimization Guide

single readout: In hdr mode, the transmission time of a single frame is the transmission time of a long frame.

total readout: In hdr mode, the time difference between the start of long frame transmission and the end of short frame transmission is the original transmission time of a composite frame.

rate: Frame interval time。

fps: Frame rate。

irq statistics: Interrupt information

total: The total number of interrupts, including frame end and err

csi over flow: Number of interrupts for overflow

csi bandwidth lack: Number of interruptions of bandwidth lack

frame dma end: The number of frame end interrupts, this number of interrupts is equal to the number of frames output by the sensor starting from stream start。

19.12 How to troubleshoot flicker issues

To investigate the cause of flicker, first confirm the source of flicker, which can be analyzed from the AE log.

AE log printing is turned on as follows:

1、Terminal (serial port or adb shell) execution: export persist_camera_engine_log=0x1ff3

2、Run librkaiq.so in the same terminal in step 1, through rkisp_demo, RkLunch.sh and other programs.

3、On the basis of steps 1 and 2, still unable to print out the AE log, maybe the default compilation method does not compile the log in, please refer to the following modification:

  czf@ISP:~/rk356x_sdk/external/camera_engine_rkaiq$ git diff
  diff --git a/CMakeLists.txt b/CMakeLists.txt
  index 46fba20..f5ea67f 100755
  --- a/CMakeLists.txt
  +++ b/CMakeLists.txt
  @ -6,9 +6,9 @ if(NOT CMAKE_BUILD_TYPE)
  FORCE)
  endif()
  -if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
  #if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
  add_definitions(-DBUILD_TYPE_DEBUG)
  -endif()
  #endif()

AE log contains information such as MeanLuma (brightness statistics), TmoMeanLuma (brightness statistics after TMO), exposure parameters, etc. Through these parameter information, the cause of flicker can be analyzed preliminarily.

AE exposure log example — original English figure, PDF page 217

AE exposure log example — original English figure, PDF page 217

Editable transcription of the screenshot (middle dots represent displayed spaces).

[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:7028:==================================HDR-AE·(enter)===============================
[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:7049:·AecRun:·SMeanLuma=0.280734,·MMeanLuma=4.009174,LMeanLuma=0.000000,TmoMeanLuma=6.188991,Isconverged=0,Longfrm=0
[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:7058:·>>>·Framenum=5·Cur·Piris=128,·sgain=1.000000,Stime=0.000505,mgain=1.000000,mtime=0.003005,lgain=1.000000,ltime=0.003000
[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:3887:·S-HighLightLuma=16.500000,S-Target=110.000000,S-GlobalLuma=0.280734,S-Target=15.662778
[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:4264:·T-LowLightLuma=3.848156,T-Target=50.000000,L-GlobalLuma=4.009174,L-Target=75.000000
[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:5725:·AecHdrClmExecute:·sgain=1.000000,stime=0.002510,mgain=2.148907,mtime=0.020000,lgain=0.000000,ltime=0.000000
[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:7162:·calc·result:·piris=128,sgain=1.000000,stime=0.002514,mgain=2.137962,mtime=0.020000,lgain=0.000000,ltime=0.000000
[AEC]:XCAM·DEBUG·rk_aiq_ae_algo.cpp:7166:==================================(exit)===============================

Flicker analysis:

1. The flicker caused by TMO synthesis is as shown in the figure below. After the log is filtered, you can clearly see the statistical values of the short frame and the medium frame (the statistical value of the medium frame in the two-frame mode is the statistical value of the long frame) has been stable, but the statistical value after TMO But there is a jump, indicating that the relevant parameters of TMO are not applicable in some scenarios. At this step, you can refer to the tunning guide document to adjust the parameters. If it still cannot be solved, please contact the IQ engineer of RK for assistance.

TMO brightness jump log example — original English figure, PDF page 217

TMO brightness jump log example — original English figure, PDF page 217

Editable transcription of the screenshot (middle dots represent displayed spaces).

AecRun: SMeanLuma=3.642202, MMeanLuma=59.557796,LMeanLuma=0.000000,TmoMeanLuma=46.662384,Isconverged=1,Longfrm=0
AecRun: SMeanLuma=3.638532, MMeanLuma=59.590824,LMeanLuma=0.000000,TmoMeanLuma=46.708256,Isconverged=1,Longfrm=0
AecRun: SMeanLuma=3.644037, MMeanLuma=59.631191,LMeanLuma=0.000000,TmoMeanLuma=46.691742,Isconverged=1,Longfrm=0
AecRun: SMeanLuma=3.642202, MMeanLuma=59.647705,LMeanLuma=0.000000,TmoMeanLuma=46.713760,Isconverged=1,Longfrm=0
AecRun: SMeanLuma=3.638532, MMeanLuma=59.598164,LMeanLuma=0.000000,TmoMeanLuma=64.000000,Isconverged=1,Longfrm=0
AecRun: SMeanLuma=3.640367, MMeanLuma=59.543118,LMeanLuma=0.000000,TmoMeanLuma=46.702751,Isconverged=1,Longfrm=0
AecRun: SMeanLuma=3.644037, MMeanLuma=59.620182,LMeanLuma=0.000000,TmoMeanLuma=46.719265,Isconverged=1,Longfrm=0
AecRun: SMeanLuma=3.631193, MMeanLuma=59.620182,LMeanLuma=0.000000,TmoMeanLuma=46.746788,Isconverged=1,Longfrm=0

2. The statistic value on raw is very stable, and the statistic value after TMO is also very stable, but flickering can still be seen on the screen, indicating that there is a problem that caused flickering in the subsequent modules of the isp. Please contact the RK engineer for further analysis after troubleshooting. .

3. When flickering occurs when time and gain change at the same time, it indicates that there may be a problem with the configuration of the effective time of time gain. Generally, the time of the sensor is n+2 to take effect, and gain n+2, n+1 are more frequent. If you know the time, For the gain effective frame, you can fill in the parameters in the iq file for testing. The following is the xml version of the iq file description. The value 2 means that n+2 is effective, and n means that the frame header of the nth frame will set the exposure parameters down. The json version parameters are similar, please refer to the document configuration by yourself.

  <EXP_DELAY index="1" type="struct" size="[1 1]">
         <Normal index="1" type="struct" size="[1 1]">
              <time_delay index="1" type="double" size="[1 1]">
              [2 ]
          </time_delay>
              <gain_delay index="1" type="double" size="[1 1]">
              [2 ]
          </gain_delay>
              <dcg_delay index="1" type="double" size="[1 1]">
              [1 ]
          </dcg_delay>
        </Normal>
        <Hdr index="1" type="struct" size="[1 1]">
           <time_delay index="1" type="double" size="[1 1]">
              [2]
           </time_delay>
           <gain_delay index="1" type="double" size="[1 1]">
              [2]
           </gain_delay>
           <dcg_delay index="1" type="double" size="[1 1]">
              [1]
           </dcg_delay>
        </Hdr>
  </EXP_DELAY>

If the effective frame cannot be determined, there is an AecSyncTest node in the AE module in the iq file for testing. The principle of this module is two sets of exposure parameters, which are switched back and forth at a certain number of frames. You can set the time of the two sets of parameters to the same value, and set the gain to different values, and then analyze the MeanLuma statistical value of the AE log and the corresponding time gain parameter value.

4. If the time is stable when flashing, and the gain value is called back, there may be a problem with the conversion formula of gain, or the linearity of the sensor itself is relatively poor.

4.1 The conversion formula is related to sensor conversion instructions and driver writing. For detailed instructions, please refer to Sensor Info Filling Guide. You can calculate the value converted from the time gain on the AE log to the register, and compare it with the time gain register value printed by the driver to see if the register value calculated by yourself is consistent with the value calculated by the program. If it is inconsistent, you need to confirm the conversion formula and driver. To see if there is a problem.

4.2 Linearity problem, you can confirm the linearity by grabbing the raw image and using the image viewing tool to obtain image statistics.

4.2.1 Time linearity test:

a. Cover with frosted glass (it can be replaced by thin paper towels, the function is to make the entire image light evenly in the linear region), fix the gain value to 1, respectively grab 10ms, 20ms, and 30ms raw maps to obtain statistical values (the statistical value of general software is 8bit, range 0~255), record form

b. The lens is completely black, grab a raw image, the statistical value of this image is the black level value. (Because the accuracy requirements are not high, the time gain value here is not required. Don’t be too exaggerated. For example, the gain of the test is set at 1x, and the raw map of the black level is set at 1000x. This will affect the statistical value, not advisable)

c. In the table, subtract the black level of step b from the statistical value recorded in step a, and make a broken line graph of the statistical value of the subtracted black level and the exposure time. If it is a straight line or close to a straight line, the linearity can be considered as good.

Note:

1. There are supported_modes in the driver. There are vts_def (frame length in the default configuration, including field blanking) and frame rate in the configuration table. The exposure time can be easily converted through two parameters. Assuming that the frame rate is 30fps, vts_def is 1200, and the frame interval is 1s/30fps=33.333ms, the exposure behavior corresponding to 10ms is 10/33.333*1200=360 lines, and the exposure parameter settings refer to How to set the exposure parameters of CIS

2. The statistical value of the raw image captured in step a must be greater than the black level and less than 180

4.2.2 Gain linearity

a. Cover the frosted glass and fix the time value to 10ms. Grab the raw graphs of gain values such as 1x 2x 4x 8x to obtain the statistical values (the statistical value of general software is 8bit, the range is 0~255), and record the table. If some gain values are under When the statistical value of is not below 180, the time value can be adjusted and the test can be performed in sections.

b. The lens is completely black, grab a raw image, the statistical value of this image is the black level value. (Because the accuracy requirements are not high, the time gain value here is not required. Don’t be too exaggerated. For example, the gain of the test is set at 1x, and the raw map of the black level is set at 1000x. This will affect the statistical value, not advisable)

value.

c. In the table, subtract the black level of step b from the statistical value recorded in step a, and make a broken line graph of the statistical value of the subtracted black level and the exposure time. If it is a straight line or close to a straight line, the linearity can be considered as good.

line graph with the statistical value of the subtracted black level and the gain. If it is a straight line or close to a straight line, the linearity can be considered as good.

Note:

1. The statistical value of the raw image captured in step a must be greater than the black level and less than 180

2. If you suspect that there is a problem with the linearity of a certain gain value, you can test the linearity of this section separately, and you do not need to test the linearity of the complete gain interval.

5. In a high-bright environment, such as when the outdoor sunlight is strong, there may be flickering. There may be a problem with the exposure value and the register conversion. For example, the application layer thinks that 5 lines, through the register conversion, the actual effect may be 4 lines. There is a row of brightness deviation, and the brightness deviation of a row can easily lead to flicker in an outdoor strong light environment. It is necessary to compare the description of the exposure calculation in the sensor manual to carefully check whether the driver is implemented correctly.

19.13 How to troubleshoot the problem of purple overflow at the light source

1. Linear mode

In the linear mode, the light source is purple. It is possible that the gain value of the sensor is set to an illegal value, resulting in an abnormal image. It is necessary to check whether the gain value register of the drive conversion meets the restriction conditions described in the sensor manual.

2. HDR mode

In HDR mode, there are mainly the following two reasons:

2.1 The short-frame image offset causes the HDR synthesis to be misaligned. In this case, you can see if there are mipi-related errors in the kernel log. If there is no mipi error, further confirm whether there is any problem with the exposure parameters set to the sensor. HDR sensors usually have more restrictions on long and short frame exposure. For these restrictions, please refer to Sensor Info Filling Guide. Print out the register value written by the driver to the sensor, and compare it with the restriction conditions described in the sensor manual to see if there is a register value that does not meet the requirements.

2.2 The exposure parameter ratio of the long and short frames does not match the effective ratio of the actual image. In this case, refer to 2.1 to confirm whether there is a problem with the conversion of the exposure parameter. A more common problem is that most sensors have a limitation on the maximum exposure of short frames. Assume that the maximum exposure of a sensor is 2ms, and the sensor info and AEC parameters in the iq file do not configure the maximum short frame or short frame. The maximum limit condition is set larger than the drive limit. For example, AEC may decompose a short frame exposure of 3ms. When set to the drive, the actual maximum can only be set to 2ms, but the drive does not directly return an error to AEC, so AEC thinks that 3ms The setting is successful, and the exposure parameters are passed to the TMO module, resulting in incorrect ratio and incorrect brightness of the synthesized image. The place where the short frame is merged is usually the overexposed area, which is usually manifested in the light source, that is, the common light source is purple.

Therefore, the image light source is purple, and the key point is to check whether the exposure parameters decomposed by AEC are different from the actual exposure parameters set in the sensor.

19.14 Sensor Info Filling Guide

Take imx290 as an example:

[imx290]
CISAgainRange=1 31.6
CISDgainRange=1 125.89

When using analog gain (again) alone, when the brightness is insufficient, digital gain (dgain) is usually used to compensate. The general approach of rk is to mix dgain with again to issue, and then separate again and dgain by the driver, and set them to the corresponding sensor registers;

The Imx290 manual describes the distribution of gain values as follows:

0dB to 30 dB:Analog Gain 30 dB (step pitch 0.3dB)

30.3 dB to 72 dB: Analog Gain 30dB + Digital Gain 0.3 to 42dB (step pitch 0.3dB)

That is, again 30dB, dgain 42dB

By formula:

db = 20 * log10(gain multiple format)
reg_gain = 20 * log10(gain multiple forma) * 10 / 3

Calculate multiple unitsagain = 10^(30db/20)=31.6 x

        Dgain = 10^(42db/20) = 125.89 x
CISExtraAgainRange=2 63.2

CISExtraAgainRange is the range value of again * dcg ratio. Some sensors support HCG/LCG. HCG can obtain a better signal-to-noise ratio in a dark environment. If the driver implements related functions, you need to fill in the corresponding conversion gain value here. The Imx290 manual describes the conversion efficiency ratio with a typical value of 2, that is, when the 2x again is set, and the HCG mode is set, the actual gain value is 4x, so CISExtraAgainRange=2*[1 31.6], if the driver does not implement HCG/LCG, Fill in by default [1 1]

CISIspDgainRange=1 1

Isp dgain,Not currently used, just press the default value

CISMinFps=10

The minimum allowable frame rate, assuming that the frame needs to be downgraded to 5fps, and the sensor supports the frame down to 5fps, here must also be synchronously modified to 5 before the frame can be downgraded through iq configuration or api.

CISTimeRegMin=1

In linear mode, the smallest unit of exposure line, please refer to sensor manual for description

CISLinTimeRegMaxFac=1.00 2.00

Maximum exposure line in linear mode, please refer to sensor manual for description

CISTimeRegOdevity=1 0

The parity of the exposure line in linear mode, as described in the sensor manual, shs1 can be incremented by one, and the exposure line can also be incremented by one.

The Imx290 manual has the following: descriptionIntegration time = 1 frame period - (SHS1 + 1) X(1H period)

The Rk framework currently sends the exposure unit from aiq to the driver in line time. If part of the sensor is half line unit, it needs to be converted into line unit. From the exposure formula of imx290, it can be seen that it is line unit. The above formula is re-described below for exposure lines: time_lines = vts -shs1 - 1

From the description of shs1 in the sensor manual, the limit is 1~(Number of lines per frame - 2),the same as 1~ (vts-2)

So CISTimeRegMin = vts -shs1 - 1 = vts -(vts-2)- 1 = 1

CISLinTimeRegMaxFac = vts - shs1 - 1 = vts - 1 - 1 = vts - 2

Vts is the total number of lines in a frame, including vertical blanking. The descriptions of different manuals are slightly different. 1 frame period and Number of lines per frame both describe vts.

CISHdrTimeRegMin=1

Hdr minimum exposure line, please refer to sensor manual for description

CISHdrTimeRegMax=8 0 0

Hdr maximum exposure line. This variable is increased because some sensors have a limit on the maximum exposure line of short frames, and it cannot increase with the decrease of long frame exposure, nor can it increase with the decrease of frame rate. Imx290 is such a sensor. According to Sony’s standard configuration, the maximum number of short frame exposure lines is 8 lines. The imx307 DOL document describes the decreasing exposure ratio mode. According to the configuration inside, the maximum number of short frame exposure lines is 222 lines. The imx290 DOL document does not see the description. Please consult Sony for details. support.

CISHdrTimeRegOdevity=1.00 0.00
CISHdrTimeRegSumFac=1.00 6.00

The Sony DOL document has the following description:

DOL two-frame settings and exposure formulas — original English figure, PDF page 222

DOL two-frame settings and exposure formulas — original English figure, PDF page 222

Item Symbol Setting register Setting value / condition
Frame Set Count FSC VMAX VMAX × 2
Shutter timing of SEF1 SHS1 SHS1 2 or more and RHS1 - 2 or less
Readout timing of SEF1 RHS1 RHS1 2n+5 (n = 0, 1, 2 …) and RHS1 ≤ FSC - BRL × 2 - 21
Shutter timing of LEF SHS2 SHS2 RHS1 + 2 or more and FSC - 2 or less
Item Symbol Formula Unit Remarks
LEF exposure time t_LEF FSC - (SHS2 + 1) H -
SEF1 exposure time t_SEF1 RHS1 - (SHS1 + 1) H -
Exposure ratio - t_LEF / t_SEF1 - Combining 2 frames

CISHdrTimeRegMin:

The minimum exposure value of long frames can be calculated through the table:

exposure of long frame = FSC-SHS2-1=FSC-(FSC-2)-1=1

exposure of short frame = RHS1-SHS1-1=RHS1-(SHS1-2)-1=1

So the minimum exposure behavior under HDR is 1

CISHdrTimeRegOdevity: From the table, shs1 and shs2 have no restrictions like 2n or 2n+1, so the corresponding exposure line can be incremented by 1

CISHdrTimeRegSumFac:

The sum of long and short frame exposures =(FSC-SHS2-1)+ (RHS1-SHS1-1)

SHS2 and SHS1 take the minimum value at the same time to maximize the exposure of both the long and short frames

The sum of long and short frame exposures =(FSC-(RHS1+2)-1)+ (RHS1-2-1)=FSC-6

For 2 frames of DOL hdr, FSC=2vts, so the maximum exposure sum of long and short frames is =2vts-6

That is, CISHdrTimeRegSumFac=[2 6], but for the convenience of calculation, Sony’s DOL hdr driver will use FSC as the aec uploaded by vts, that is, the uploaded vts has actually been doubled, so CISHdrTimeRegSumFac= [1 6]

CISTimeRegUnEqualEn=1

Whether the time of the long and short frames can be equal, due to the imx290 short frame limitation, it cannot be equal under any circumstances

CISHdrGainIndSetEn=1

Whether the gain of the long and short frames needs to be set to the same, 1 means it can be set to different values, 0 means the gain of the long and short frames must be the same, see the sensor description for details, some sensors share a set of registers for the long and short frames, and some sensors have different gains in the long and short frames. However, for design reasons, the two sets of registers need to be set to the same value. In order to expose the correctness of the decomposition, this parameter needs to be filled in accurately.

Note:

imx290 needs to pay attention to the setting of FPGC PFGC_1 value, the DOL document has specific description.

FullResolution=1920x1080
GainRange=1 2 20 20 1 0 20 2 4 10 0 1 20 40 4 8 5 -20 1 40 60 8 16 2.5 -40 1 60 80 16 32 1.25 -60 1 80 100 32 64 0.625 -80 1 100 120 64 128 0.3125 -100 1 120 140 128 256 0.15625 -120 1 140 160 256 512 0.078125 -140 1 160 180 512 1024 0.0390625 -160 1 180 200
IsLinear=0

The Rk platform supports the gain value setting in multiples and the gain value setting in the sony db mode. 0 means db is used. The db method can be used directly for imx290, or the above GainRange decomposition formula can be used. The GainRange decomposition formula will have a slight error, after all The non-linear curve is broken down into multiple linear curves.

NonLinear=DB_MODE
PatternMode=RGGB
TimeFactor=0 0 1 0.5

Time decomposition formula, it is recommended to keep this formula, if the calculation does not meet the formula, the sensor driver will do the conversion.

hdr_dcg_ratio=2
normal_dcg_ratio=2

Dcg ratio has been described above

SensorFlip=0

The default mirror flip state, bit0 mirror, bit1 flip

20. Appendix A CIS driver V4L2-controls list

CID description
V4L2_CID_VBLANK Vertical blanking. The idle period after every frame during which no image data is produced. The unit of vertical blanking is a line. Every line has length of the image width plus horizontal blanking at the pixel rate defined by V4L2_CID_PIXEL_RATE control in the same sub-device.
V4L2_CID_HBLANK Horizontal blanking. The idle period after every line of image data during which no image data is produced. The unit of horizontal blanking is pixels.
V4L2_CID_EXPOSURE Determines the exposure time of the camera sensor. The exposure time is limited by the frame interval.
V4L2_CID_ANALOGUE_GAIN Analogue gain is gain affecting all colour components in the pixel matrix. The gain operation is performed in the analogue domain before A/D conversion.
V4L2_CID_PIXEL_RATE Pixel rate in the source pads of the subdev. This control is read-only and its unit is pixels / second. Ex mipi bus:pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
V4L2_CID_LINK_FREQ Data bus frequency. Together with the media bus pixel code, bus type (clock cycles per sample), the data bus frequency defines the pixel rate (V4L2_CID_PIXEL_RATE) in the pixel array (or possibly elsewhere, if the device is not an image sensor). The frame rate can be calculated from the pixel clock, image width and height and horizontal and vertical blanking. While the pixel rate control may be defined elsewhere than in the subdev containing the pixel array, the frame rate cannot be obtained from that information. This is because only on the pixel array it can be assumed that the vertical and horizontal blanking information is exact: no other blanking is allowed in the pixel array. The selection of frame rate is performed by selecting the desired horizontal and vertical blanking. The unit of this control is Hz.

21. Appendix B MEDIA_BUS_FMT table

CIS sensor type Sensor output format
Bayer RAW MEDIA_BUS_FMT_SBGGR10_1X10 MEDIA_BUS_FMT_SRGGB10_1X10 MEDIA_BUS_FMT_SGBRG10_1X10 MEDIA_BUS_FMT_SGRBG10_1X10 MEDIA_BUS_FMT_SRGGB12_1X12 MEDIA_BUS_FMT_SBGGR12_1X12 MEDIA_BUS_FMT_SGBRG12_1X12 MEDIA_BUS_FMT_SGRBG12_1X12 MEDIA_BUS_FMT_SRGGB8_1X8 MEDIA_BUS_FMT_SBGGR8_1X8 MEDIA_BUS_FMT_SGBRG8_1X8 MEDIA_BUS_FMT_SGRBG8_1X8
YUV MEDIA_BUS_FMT_YUYV8_2X8 MEDIA_BUS_FMT_YVYU8_2X8 MEDIA_BUS_FMT_UYVY8_2X8 MEDIA_BUS_FMT_VYUY8_2X8 MEDIA_BUS_FMT_YUYV10_2X10 MEDIA_BUS_FMT_YVYU10_2X10 MEDIA_BUS_FMT_UYVY10_2X10 MEDIA_BUS_FMT_VYUY10_2X10 MEDIA_BUS_FMT_YUYV12_2X12 MEDIA_BUS_FMT_YVYU12_2X12 MEDIA_BUS_FMT_UYVY12_2X12 MEDIA_BUS_FMT_VYUY12_2X12
Only Y (black and white) is raw bw sensor MEDIA_BUS_FMT_Y8_1X8 MEDIA_BUS_FMT_Y10_1X10 MEDIA_BUS_FMT_Y12_1X12

22. Appendix C CIS Reference Driver List

CIS interface Output type Frame / field Reference driver
MIPI Bayer RAW frame 0.3M: ov7750.c, gc0403.c
0.9M jx_h62.c
1.2M ov9750.c jx-h65.c
2M ov2685.c ov2680.c ov2735.c ov02g10.c ov02b10.c gc2385.c gc2355.c gc2053.c sc2232.c sc2239.c sc223a sc210iot.c sp250a.c
4M gc4c33.c jx_k04.c os04c10.c sc401ai.c
5M ov5695.c ov5648.c ov5670.c gc5024.c gc5025.c gc5035.c hm5040.c sc5239.c hynix_hi556.c
8M ov8858.c
CIS Data interface CIS Output data type Frame/Field Reference drive
      os08a10.c os08a20.c sc8220 imx378.c imx317.c imx219.c gc8034.c hynix_hi846.c s5kgm1sp.c s5k4h7yx.c 13M ov13850.c ov13b10.c imx258.c ov12d2q.c
MIPI Bayer raw hdr frame 2M imx307.c imx327.c imx462.c gc2093.c ov02k10 ov2718.c sc200ai.c sc2310.c jx-f37.c 4M ov4689.c os04a10.c imx347.c imx464.c sc4238.c 5M imx335.c os05a20.c sc500ai.c 8M imx334.c imx415.c
MIPI YUV frame 2M gc2145.c
CIS Data interface CIS Output data type Frame/Field Reference drive
MIPI RAW BW frame 0.3M ov7251.c 1M ov9281.c 1.3M sc132gs.c
MIPI YUV field tc35874x.c
ITU.BT601 Bayer RAW   2M imx323.c ar0230.c
ITU.BT601 YUV   0.3M gc0329.c gc0312.c gc032a.c 2M gc2145.c gc2155.c gc2035.c bf3925.c
ITU.BT601 RAW BW   0.3M sc031gs.c 1.3M sc032gs.c
ITU.BT656 Bayer RAW   2M imx323(Can support)

23. Appendix D VCM driver ic reference driver list

Reference driver
vm149c.c
dw9714.c
dw9718.c
fp5510.c
gt9760s.c
fp5501.c (step motor)
mp6507.c (step motor)
ms41908.c (step motor)

24. Appendix E Flash light driver ic reference driver list

Reference driver
sgm3784.c
leds-rgb13h.c (GPIO control)

Explore this topic → · Learning paths →