RK3588的硬件能力
ISP和VICAP的链接关系:
VICAP和ISP是独立的两个图像处理IP, VICAP所采集图像若要通过ISP处理,在驱动层面需要生成VICAP对应接口的v4l2 sub device链接到ISP对应的节点,以提供参数给ISP驱动使用。
1.RKISP 驱动
RKISP驱动主要是依据v4l2 / media framework实现硬件的配置、中断处理、控制 buffer轮转,以及控制subdevice(如 mipi dphy及sensor)的上下电等功能。
下面的框图描述了RKISP驱动的拓扑结构:
各节点描述如下:
csi subdev通过get_fmt获取sensor驱动多个pad格式的输出信息,对应csi的source pad。
2.RKVICAP 驱动
RKVICAP驱动主要是基于v4l2 / media框架实现硬件的配置、中断处理、控制 buffer轮转,以及控制subdevice(如 mipi dphy及sensor)的上下电等功能。
VICAP只有单核,同时拥有dvp/mipi两种接口,dvp接口对应一个rkvicap_dvp节点,mipi接口对应一个rkvicap_mipi_lvds节点,各节点可独立采集。
为了将VICAP采集数据信息同步给isp驱动,需要将VICAP驱动生成的逻辑sditf节点链接到isp所生成的虚拟节点设备。DVP接口对应rkvicap_dvp_sditf节点,VICAP FULL的mipi/lvds接口对应rkvicap_mipi_lvds_sditf节点,VICAP LITE对应rkvicap_lite_sditf。
3.RK3588 VI结构
硬件支持最多采集7路sensor:6mipi + 1dvp,多sensor软件通路如下:
1. rk3588支持两个dcphy,节点名称分别为csi2_dcphy0/csi2_dcphy1。每个dcphy硬件支持RX/TX同时使用,对于camera输入使用的是RX。支持DPHY/CPHY协议复用;需要注意的是同一个dcphy的TX/RX只能同时使用DPHY或同时使用CPHY。其他dcphy参数请查阅rk3588数据手册。 2. rk3588支持2个dphy硬件,这里我们称之为dphy0_hw/dphy1_hw,两个dphy硬件都可以工作在fullmode 和split mode两种模式下。 3. 当dphy0_hw使用full mode时,链路需要按照csi2_dphy1这条链路来配置,但是节点名称csi2_dphy1需要修改为csi2_dphy0,软件上是通过phy的序号来区分phy使用的模式。 2. dphy1_hw 1. full mode:节点名称使用csi2_dphy3,最多支持4 lane。 2. split mode: 拆分成2个phy使用,分别为csi2_dphy4(使用0/1 lane)、csi2_dphy5(使用2/3 lane),每个phy最多支持2 lane。 3. 当dphy1_hw使用full mode时,链路需要按照csi2_dphy4这条链路来配置,但是节点名称csi2_dphy4需要修改为csi2_dphy3,软件上是通过phy的序号来区分phy使用的模式。 3. 使用上述mipi phy节点,需要把对应的物理节点配置上。(csi2_dcphy0_hw/csi2_dcphy1_hw/csi2_dphy0_hw/csi2_dphy1_hw) 4. 每个mipi phy都需要一个csi2模块来解析mipi协议,节点名称分别为mipi0_csi2~mipi5_csi2。 5. rk3588所有camera数据都需要通过vicap,再链接到isp。rk3588仅支持一个vicap硬件,这个vicap支持同时输入6路mipi phy,及一路dvp数据,所以我们将vicap分化成rkcif_mipi_lvds~rkcif_mipi_lvds5、rkcif_dvp等7个节点,各个节点的绑定关系需要严格按照框图的节点序号配置。 6. 每个vicap节点与isp的链接关系,通过对应虚拟出的XXX_sditf来指明链接关系。 7. rk3588支持2个isp硬件,每个isp设备可虚拟出多个虚拟节点,软件上通过回读的方式,依次从ddr读取每一路的图像数据进isp处理。对于多摄方案,建议将数据流平均分配到两个isp上。 8. 直通与回读模式: 1. 直通:指数据经过vicap采集,直接发送给isp处理,不存储到ddr。需要注意的是hdr直通时,只有短帧是真正的直通,长帧需要存在ddr,isp再从ddr读取。 2. 回读:指数据经过vicap采集到ddr,应用获取到数据后,将buffer地址推送给isp,isp再从ddr获取图像数据。 3. 再dts配置时,一个isp硬件,如果只配置一个虚拟节点,默认使用直通模式,如果配置了多个虚拟节点默认使用回读模式。 |
4.CIS(cmos image sensor)驱动
imx464接dphy1为例:
- data-lanes必须指明具体使用的lane数,否则无法识别为mipi 类型;
- dphy需要链接到csi host节点,csi2_dphy3对应使用mipi4_csi2;
- csi2_dphy3只是逻辑节点,需要依赖物理节点csi2_dphy1_hw。
- rkcif_mipi_lvds4是vicap的其中一个逻辑节点,物理节点rkcif及对应iommu需要配置上。rkcif_mipi_lvds4_sditf是虚拟子节点,是rkcif_mipi_lvds4的虚拟节点,用来链接isp。
- sensor驱动一般实现avdd/dvdd/dovdd三个电源操作,如果使用类似rk809分配出来的电源可以直接在sensor节点配置上,如果使用LDO等外部电源,使能脚是通过gpio控制,可以参考vcc_mipicsi1配置成电源节点,可以通过引用计数来上下电,适用于多设备使用同一电源。建议多摄时dvdd电源分开供应,avdd/dovdd可以共用,dvdd共用时,如果功率比较大,可能出现瞬时供应不足,电源有塌陷,影响到图像质量,甚至不出图。
/ {cam_ircut0: cam_ircut {status = "okay";compatible = "rockchip,ircut";ircut-open-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;ircut-close-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;rockchip,camera-module-index = <0>;rockchip,camera-module-facing = "back";};vcc_mipidphy0: vcc-mipidcphy0-regulator {compatible = "regulator-fixed";gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;pinctrl-names = "default";pinctrl-0 = <&mipidphy0_pwr>;regulator-name = "vcc_mipidphy0";enable-active-high;};
};&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>;};};port@1 {reg = <1>;#address-cells = <1>;#size-cells = <0>;csidphy0_out: endpoint@0 {reg = <0>;remote-endpoint = <&mipi2_csi2_input>;};};};
};&csi2_dphy0_hw {status = "okay";
};&i2c3 {status = "okay";imx415: imx415@1a {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_PB3 GPIO_ACTIVE_HIGH>;avdd-supply = <&vcc_mipidphy0>;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";lens-focus = <&cam_ircut0>;port {imx415_out0: endpoint {remote-endpoint = <&mipidphy0_in_ucam0>;data-lanes = <1 2 3 4>;};};};
};&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>;};};};
};&pinctrl {cam {mipidphy0_pwr: mipidphy0-pwr {rockchip,pins =/* camera power en */<1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;};};
};&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>;};};
};
5.RK3588 camera驱动移植步骤
- 根据struct i2c_driver说明实现以下成员
struct driver.name
struct driver.pm
struct driver. of_match_table
probe函数
remove函数 - probe函数实现细节描述: CIS 设备资源的获取,主要是解析DTS文件中定义资源,RK私有资源定义,命名方式如下rockchip,camera-module-xxx, 该部分资源会由驱动上传给用户态的camera_engine来决定IQ效果参数的匹配
- CIS设备资源定义,RK相关参考驱动一般包含以下几项:
- CIS设备ID号检查, 通过以上步骤获取必要资源后,建议驱动读取设备ID号以便检查硬件的准确性,当然该步骤非必要步骤.
- CIS v4l2设备以及media实体的初始化。v4l2子设备:v4l2_i2c_subdev_init,RK CIS驱动要求subdev拥有自己的设备节点供用户态rk_aiq访问,通过该设备节点实现曝光控制;media实体:media_entity_init
struct v4l2_subdev_ops说明实现v4l2子设备驱动,主要实现以下3个成员:
- struct v4l2_subdev_core_ops
- struct v4l2_subdev_video_ops
- struct v4l2_subdev_pad_ops
struct v4l2_subdev_core_ops实现其回调函数,主要实现以下回调:
- .s_power
s_power实现sensor的上下电操作,对于一些寄存器数组较长的sensor,可以归纳出公共部分的寄存器,在上电后执行,s_stream只配置不同分辨率配置必须的寄存器,加快切换速度。
- .ioctl .compat_ioctl32
ioctl主要实现的RK私有控制命令
struct v4l2_subdev_video_ops主要实现以下回调函数:
struct v4l2_subdev_pad_ops主要实现以下回调函数:
struct v4l2_ctrl_ops主要实现以下回调
.s_ctrl | RKISP driver、camera_engine通过设置不同的命令来实现CIS 曝光控制; |