一、簡介
-
MIPI聯盟,即移動產業處理器接口(Mobile Industry Processor Interface 簡稱MIPI)聯盟。MIPI(移動產業處理器接口)是 MIPI聯盟發起的為移動應用處理器制定的開放標準和一個規范。
-
CSI & DSI
? CSI ( Camera Serial Interface ):攝像頭接口
? DSI ( Display Serial Interface ):顯示接口
二、 名詞解釋:
- ISP ( Image Signal Processor ): 即圖像信號處理模塊, 主要作用是對前端圖像傳感器輸出的信號做后期處理,依賴于 ISP 才能在不同的光學條件下都能較好的還原現場細節。
- VICAP( Video capture ):視頻捕獲單元
三、RK3588 的camera通路:
多sensor支持:
- 單路硬件isp最多支持4路復用,isp復用情況支持分辨率如下:
- 2路復用:最大分辨率3840x2160,dts對應配置2路rkisp_vir設備。
- 3路或4路復用:最大分辨率2560x1536,dts對應配置3或4路rkisp_vir設備。
- 硬件支持最多采集7路sensor:6mipi + 1dvp,多sensor軟件通路如下:
下圖是RK3588 camera連接鏈路示意圖,可以支持7路camera。
四、 鏈路解析:
-
圖中:mipi camera2---> csi2_dphy1 ---> mipi2_csi2 ---> rkcif_mipi_lvds2--->rkcif_mipi_lvds2_sditf --->rkisp0_vir2
-
對應節點:imx415 ---> csi2_dphy0 ---> mipi2_csi2 ---> rkcif_mipi_lvds2--->rkcif_mipi_lvds2_sditf --->rkisp0_vir2
-
鏈接關系:sensor---> csi2 dphy---->mipi csi host--->vicap
-
實線鏈路解析: Camera sensor ---> dphy ---> 通過mipi_csi2模塊解析mipi協議---> vicap ( rkcif節點代表vicap )
-
虛線鏈路解析:vicap ---> rkcif_mipi_lvds2_sditf ---> isp
每個vicap節點與isp的鏈接關系,通過對應虛擬出的XXX_sditf來指明鏈接關系。
五、RK3588硬件通路框圖
- rk3588支持2個isp硬件,每個isp設備可虛擬出多個虛擬節點,軟件上通過回讀的方式,依次從ddr讀取每一路的圖像數據進isp處理。對于多攝方案,建議將數據流平均分配到兩個isp上。
- 回讀:指數據經過vicap采集到ddr,應用獲取到數據后,將buffer地址推送給isp,isp再從ddr獲取圖像數據。
六、詳細解析:
- imx415 : Camera sensor
- csi2_dphy0 : rk3588支持2個dphy硬件,這里我們稱之為dphy0_hw/dphy1_hw ,,兩個dphy硬件都可以工作在full mode 和split mode兩種模式下。
當使用dphy0_hw:
- full mode:節點名稱使用csi2_dphy0,最多支持4 lane。
當dphy0_hw使用full mode時,鏈路需要按照csi2_dphy1這條鏈路來配置,但是節點名稱csi2_dphy1需要修改為csi2_dphy0,軟件上是通過phy的序號來區分phy使用的模式。 - split mode:拆分成2個phy使用,分別為csi2_dphy1(使用0/1 lane)、csi2_dphy2(使用2/3 lane),每個phy最多支持2 lane。
當使用dphy1_hw:
- full mode:節點名稱使用csi2_dphy3,最多支持4 lane。
當dphy1_hw使用full mode時,鏈路需要按照csi2_dphy4這條鏈路來配置,但是節點名稱csi2_dphy4需要修改為csi2_dphy3,軟件上是通過phy的序號來區分phy使用的模式。 - split mode:拆分成2個phy使用,分別為csi2_dphy4(使用0/1 lane)、csi2_dphy5(使用2/3 lane),每個phy最多支持2 lane。
-
dcphy:
rk3588支持兩個dcphy,節點名稱分別為csi2_dcphy0/csi2_dcphy1。每個dcphy硬件支持RX/TX同時使用,對于camera輸入使用的是RX。支持DPHY/CPHY協議復用;需要注意的是同一個dcphy的TX/RX只能同時使用DPHY或同時使用CPHY。其他dcphy參數請查閱rk3588數據手冊。 -
使用上述mipi phy節點,需要把對應的物理節點配置上。
(csi2_dcphy0_hw/csi2_dcphy1_hw/csi2_dphy0_hw/csi2_dphy1_hw) -
每個mipi phy都需要一個csi2模塊來解析mipi協議,節點名稱分別為mipi0_csi2~mipi5_csi2。
-
rk3588所有camera數據都需要通過vicap,再鏈接到isp。rk3588僅支持一個vicap硬件,這個vicap支持同時輸入6路mipi phy,及一路dvp數據,所以我們將vicap分化成rkcif_mipi_lvds~rkcif_mipi_lvds5、rkcif_dvp等7個節點,各個節點的綁定關系需要嚴格按照框圖的節點序號配置。
-
每個vicap節點與isp的鏈接關系,通過對應虛擬出的XXX_sditf來指明鏈接關系。
-
rk3588支持2個isp硬件,每個isp設備可虛擬出多個虛擬節點,軟件上通過回讀的方式,依次從ddr讀取每一路的圖像數據進isp處理。對于多攝方案,建議將數據流平均分配到兩個isp上。
-
直通與回讀模式:
?直通:指數據經過vicap采集,直接發送給isp處理,不存儲到ddr。需要注意的是hdr直通時,只有短幀是真正的直通,長幀需要存在ddr,isp再從ddr讀取。?回讀:指數據經過vicap采集到ddr,應用獲取到數據后,將buffer地址推送給isp,isp再從ddr獲取圖像數據。
?在dts配置時,一個isp硬件,如果只配置一個虛擬節點,默認使用直通模式,如果配置了多個虛擬節點默認使用回讀模式。
七、單路Camera的dts配置說明:( 以imx415攝像頭為例 )
- 案例場景:這里使用的是csi2_dphy0的單路camera配置:
- 鏈路配置: imx415 —> csi2_dphy0 —> mipi2_csi2 —> rkcif_mipi_lvds2—>rkcif_mipi_lvds2_sditf —>rkisp0_vir2
&i2c3 {
status = "okay";
imx415: imx415@1a {
status = "okay";
compatible = "sony,imx415";
reg = < 0x1a >;
clocks = < &cru CLK_MIPI_CAMARAOUT_M3 >;
clock-names = "xvclk";
pinctrl-names = "default";
pinctrl-0 = < &mipim0_camera3_clk >;
power-domains = < &power RK3588_PD_VI >;
pwdn-gpios = < &gpio1 RK_PB0 GPIO_ACTIVE_HIGH >;
reset-gpios = < &gpio4 RK_PA0 GPIO_ACTIVE_LOW >;
rockchip,camera-module-index = < 0 >;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "CMK-OT2022-PX1";
rockchip,camera-module-lens-name = "IR0147-50IRC-8M-F20";
port {
imx415_out0: endpoint {
remote-endpoint = < &mipidphy0_in_ucam0 >;
data-lanes = < 1 2 3 4 >;
};
};
};
camera_imx219: camera-imx219@10 {
status = "disabled";
compatible = "sony,imx219";
reg = < 0x10 >;
clocks = < &clk_cam_24m >;
clock-names = "xvclk";
rockchip,camera-module-index = < 0 >;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "rpi-camera-v2";
rockchip,camera-module-lens-name = "default";
port {
imx219_out0: endpoint {
remote-endpoint = < &mipidphy0_in_ucam1 >;
data-lanes = < 1 2 >;
};
};
};
};
&csi2_dphy0_hw {
status = "okay";
};
&csi2_dphy0 {
status = "okay";
ports {
#address-cells = < 1 >;
#size-cells = < 0 >;
port@0 {
reg = < 0 >;
#address-cells = < 1 >;
#size-cells = < 0 >;
mipidphy0_in_ucam0: endpoint@1 {
reg = < 1 >;
remote-endpoint = < &imx415_out0 >;
data-lanes = < 1 2 3 4 >;
};
mipidphy0_in_ucam1: endpoint@2 {
reg = < 2 >;
remote-endpoint = < &imx219_out0 >;
data-lanes = < 1 2 >;
};
};
port@1 {
reg = < 1 >;
#address-cells = < 1 >;
#size-cells = < 0 >;
csidphy0_out: endpoint@0 {
reg = < 0 >;
remote-endpoint = < &mipi2_csi2_input >;
};
};
};
};
&mipi2_csi2 {
status = "okay";
ports {
#address-cells = < 1 >;
#size-cells = < 0 >;
port@0 {
reg = < 0 >;
#address-cells = < 1 >;
#size-cells = < 0 >;
mipi2_csi2_input: endpoint@1 {
reg = < 1 >;
remote-endpoint = < &csidphy0_out >;
};
};
port@1 {
reg = < 1 >;
#address-cells = < 1 >;
#size-cells = < 0 >;
mipi2_csi2_output: endpoint@0 {
reg = < 0 >;
remote-endpoint = < &cif_mipi2_in0 >;
};
};
};
};
&rkcif {
status = "okay";
};
&rkcif_mipi_lvds2 {
status = "okay";
port {
cif_mipi2_in0: endpoint {
remote-endpoint = < &mipi2_csi2_output >;
};
};
};
&rkcif_mipi_lvds2_sditf {
status = "okay";
port {
mipi_lvds2_sditf: endpoint {
remote-endpoint = < &isp0_vir0 >;
};
};
};
&rkcif_mmu {
status = "okay";
};
&rkisp0 {
status = "okay";
};
&isp0_mmu {
status = "okay";
};
&rkisp0_vir0 {
status = "okay";
port {
#address-cells = < 1 >;
#size-cells = < 0 >;
isp0_vir0: endpoint@0 {
reg = < 0 >;
remote-endpoint = < &mipi_lvds2_sditf >;
};
};
};
&pinctrl {
camera {
cam_pwdn_gpio: cam-pwdn-gpio {
rockchip,pins = < 1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up >;
};
};
};