资讯动态

Linux 内核 Rockchip Camera Interface(rkcif)驱动详解:从 PX30 VIP 到 RK3588 VICAP 的媒体控制器拓扑

发布时间:2026/9/10 23:16:34 来源:尧图企业网站定制
Linux 内核 Rockchip Camera Interfacerkcif驱动详解从 PX30 VIP 到 RK3588 VICAP 的媒体控制器拓扑【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux导读Rockchip Camera InterfaceCIF是 Rockchip 众多 SoC 中负责接收摄像头图像数据的硬件单元它以多种变体存在于 PX30、RK3568、RK3588 等芯片中。本文以内核文档 Documentation/admin-guide/media/rkcif.rst 为核心结合 drivers/media/platform/rockchip/rkcif 目录下的实际驱动源码系统讲解 CIF 的通用构建块DVP/MIPI CSI-2/CROP/DMA 等、三个典型硬件变体PX30 VIP、RK3568 VICAP、RK3588 VICAP在媒体控制器media controller架构下呈现的 V4L2 subdevice 与 video device 拓扑以及驱动内部对 ping-pong 双缓冲、虚拟通道VC多流等机制的实现。读完本文你将能够看懂任意一块 Rockchip 开发板上rkcif-*设备节点的含义并能依据设备树 compatible 与驱动 match data 定位到对应的硬件变体与源码实现。CIF 是什么一套由通用构建块组合出的硬件族Rockchip CIF 并非单一 IP而是一系列功能模块的组合不同 SoC 通过选取不同的构建块拼出不同能力的视频输入单元。根据 rkcif.rst 的 Introduction 章节这些通用构建块包括INTERFACE 块视频数据的入口分为两种类型——Digital Video PortDVP并行数据接口可接收并行视频数据、BT.656、BT.1120 等协议MIPI CSI-2 receiver 接口块接收 MIPI CSI-2 串行数据。CROP 单元对输入图像进行裁剪。MIPI CSI-2 receiver并非所有变体都有文档特别指出该单元在 Rockchip 文档中被称为MIPI CSI HOST从硬件上讲它是独立的一块但由于与 CIF 强耦合因此一并纳入 CIF 的讨论范围。MUX 单元并非所有变体都有将视频数据传递给图像信号处理器ISP。SCALE 单元并非所有变体都有对图像进行缩放。DMA 引擎通过名为ping-pong mode的双缓冲机制把视频数据传输到系统内存。每个 INTERFACE 块支持四条视频流并非所有变体都有例如用于承载 MIPI CSI-2 的多个Virtual ChannelVC。正是这些构建块的组合差异形成了下文介绍的多个硬件变体。文档还点明了 CIF 的软件定位这些变体统一由位于drivers/media/platform/rockchip/rkcif的、以媒体控制器media controller为中心的rkcif设备驱动来表示。这一media controller centric的定位直接决定了内核中呈现出来的实体组织方式每个 INTERFACE/CROP 块是一个 V4L2 subdevice每个 DMA 引擎是一个 V4L2 video device二者之间通过媒体链路media link连接。硬件变体一Rockchip PX30 Video Input ProcessorVIPPX30 的 VIP 是最简单的变体它只提供一个DVP 数字视频端口可接收并行视频数据parallel video dataBT.656由于这两种协议本身不携带多条流no multiple streams因此 VIP 只配备一个 DMA 引擎负责将输入视频数据搬运到系统内存。对应的驱动表示rkcif driver同样简洁一个V4L2 subdeviceDVP INTERFACE/CROP 块一个V4L2 deviceDVP DMA 引擎。这一一进一出的极简拓扑在源码中也有清晰对应。查看 rkcif-dev.c 中的平台匹配数据static const char *const px30_vip_clks[] { aclk, hclk, pclk, }; static const struct rkcif_match_data px30_vip_match_data { .clks px30_vip_clks, .clks_num ARRAY_SIZE(px30_vip_clks), .dvp rkcif_px30_vip_dvp_match_data, };PX30 VIP 需要aclk、hclk、pclk三路时钟并且只注册了 DVP 部分rkcif_px30_vip_dvp_match_data没有 MIPI 相关数据——这与文档所述仅有 DVP、无 MIPI CSI-2 receiver完全吻合。该 match data 通过设备树 compatible 字符串rockchip,px30-vip绑定见 rkcif-dev.c 的of_device_id表。硬件变体二Rockchip RK3568 Video CaptureVICAPRK3568 VICAP 的能力明显增强它同时具备DVP与MIPI CSI-2 receiver二者可以独立接收视频数据。接口能力DVP接受并行视频数据、BT.656、BT.1120MIPI CSI-2 receiver独立接收 MIPI CSI-2 数据。由于BT.1120 协议可以携带多条流RK3568 VICAP 的 DVP 配备了四个 DMA 引擎可分别捕获不同的流同理其 MIPI CSI-2 receiver 也配备四个 DMA 引擎用于处理不同的Virtual ChannelVC。驱动的设备表示如下V4L2 subdevicerkcif-dvp0DVP 的 INTERFACE/CROP 块V4L2 video devicerkcif-dvp0-id0代表 RK3568 DVP 的第一个 DMA 引擎。文档特别说明了一个值得注意的现状DVP 上多流支持尚未实现——原因是很难找到测试硬件hard to find test hardware。因此目前rkcif-dvp0-id0仅代表 DVP 的第一个 DMA 引擎其余三个 DMA 引擎尚未暴露为独立的 video device。RK3568 VICAP 的完整拓扑见文档所附的 rkcif-rk3568-vicap.dotGraphviz 图源码被.. kernel-figure::指令渲染为内核文档中的拓扑图其节点关系如下it6801 2-0048 (/dev/v4l-subdev1) ──port0──▶ rkcif-dvp0 (/dev/v4l-subdev0) │ port1 ▼ rkcif-dvp0-id0 (/dev/video0)在该示例拓扑中一颗it6801HDMI 转并行/数字视频桥挂在 I2C 地址 2-0048作为视频源其 port0 连接到rkcif-dvp0的 sink padport0rkcif-dvp0的 source padport1再连接到 DMA 引擎对应的 video devicerkcif-dvp0-id0/dev/video0。这也解释了为什么 DVP 多流暂未实现示例中 DVP 只接了单一的视频源。源码侧RK3568 的匹配数据位于 rkcif-dev.c其时钟为aclk、hclk、dclk、iclk四路并且同时注册了 DVP 与 MIPI 两个子系统rkcif_rk3568_vicap_dvp_match_data与rkcif_rk3568_vicap_mipi_match_data对应的 compatible 字符串为rockchip,rk3568-vicap。硬件变体三Rockchip RK3588 Video CaptureVICAPRK3588 VICAP 是目前文档中能力最完整的变体它包含一个DVP和六个可独立接收视频数据的 MIPI CSI-2 capture interface。接口能力DVP接受并行视频数据、BT.656、BT.1120每个 MIPI CSI-2 receiver独立接收数据。多流能力由于 BT.1120 可携带多条流RK3588 VICAP 的 DVP 配备四个 DMA 引擎同样地每个 MIPI CSI-2 receiver 各配备四个 DMA 引擎分别对应不同的 Virtual ChannelVC。驱动的设备表示如下V4L2 subdevice共四个dw-mipi-csi2rx fdd30000.csi连接到MIPI DPHY0的 MIPI CSI-2 receiverdw-mipi-csi2rx fdd50000.csi连接到MIPI DPHY1的 MIPI CSI-2 receiverrkcif-mipi2连接到 MIPI DPHY0 的 MIPI CSI-2 receiver 所对应的 INTERFACE/CROP 块rkcif-mipi4连接到 MIPI DPHY1 的 MIPI CSI-2 receiver 所对应的 INTERFACE/CROP 块。V4L2 video device共八个rkcif-mipi2-id{0,1,2,3}连接在rkcif-mipi2INTERFACE/CROP 块上的四个 DMA 引擎rkcif-mipi4-id{0,1,2,3}连接在rkcif-mipi4INTERFACE/CROP 块上的四个 DMA 引擎。从命名规律可以看出rkcif-mipi2/rkcif-mipi4中的数字直接对应 rkcif-common.h 中的接口索引枚举RKCIF_MIPI1RKCIF_MIPI6而-id{0..3}对应同文件中的流索引枚举RKCIF_ID0RKCIF_ID3RKCIF_ID_MAX为 4即每个接口最多四条流。这些枚举贯穿整个驱动的注册与中断分发逻辑。RK3588 的完整拓扑见文档所附的 rkcif-rk3588-vicap.dot图中节点关系可概括为两条对称的 MIPI 通路imx415 3-001a (/dev/v4l-subdev4) ──▶ dw-mipi-csi2rx fdd30000.csi (/dev/v4l-subdev2) └─▶ rkcif-mipi2 (/dev/v4l-subdev0) ├─▶ rkcif-mipi2-id0 (/dev/video0) ├─▶ rkcif-mipi2-id1 (/dev/video1) ├─▶ rkcif-mipi2-id2 (/dev/video2) └─▶ rkcif-mipi2-id3 (/dev/video3) imx415 4-001a (/dev/v4l-subdev5) ──▶ dw-mipi-csi2rx fdd50000.csi (/dev/v4l-subdev3) └─▶ rkcif-mipi4 (/dev/v4l-subdev1) ├─▶ rkcif-mipi4-id0 (/dev/video4) ├─▶ rkcif-mipi4-id1 (/dev/video5) ├─▶ rkcif-mipi4-id2 (/dev/video6) └─▶ rkcif-mipi4-id3 (/dev/video7)在 dot 源码中rkcif-mipi2的 source padport1到id0是实线n00000007:port1 - n0000000a到id1/id2/id3是虚线styledashed这表示在默认配置下只有id0对应的链路处于启用enabled状态其余流需要通过媒体控制器 API 手动激活——这与每条流对应一个 VC的多流设计一致。RK3588 的匹配数据见 rkcif-dev.c时钟多达五路aclk、hclk、dclk、iclk、iclk1且match data 只包含 MIPI 部分rkcif_rk3588_vicap_mipi_match_data对应 compatiblerockchip,rk3588-vicap。从数据结构看六个 MIPI 接口的索引RKCIF_MIPI1RKCIF_MIPI6与寄存器块偏移映射定义在rkcif_mipi_match_data的blocks[]数组中见 rkcif-common.h。驱动实现纵深从平台匹配到 ping-pong 双缓冲模块构成与编译配置rkcif 驱动由五个源文件组成见 Makefilerockchip-cif-objs rkcif-capture-dvp.o # DVP 捕获通路DMA 引擎、中断 rockchip-cif-objs rkcif-capture-mipi.o # MIPI 捕获通路DMA 引擎、中断 rockchip-cif-objs rkcif-dev.o # 平台驱动、probe、匹配数据、电源管理 rockchip-cif-objs rkcif-interface.o # INTERFACE/CROP 块对应的 subdevice rockchip-cif-objs rkcif-stream.o # 流管理vb2、ping-pong、格式处理编译产物为内核模块rockchip-cif由 Kconfig 中的CONFIG_VIDEO_ROCKCHIP_CIF控制见 Kconfig。该配置项为tristate依赖VIDEO_DEV、V4L_PLATFORM_DRIVERS、PM COMMON_CLK等并会select MEDIA_CONTROLLER、VIDEOBUF2_DMA_CONTIG、V4L2_FWNODE、VIDEO_V4L2_SUBDEV_API——也就是说只要启用 rkcif媒体控制器MC与 V4L2 subdevice API 就会被自动拉入构建这正呼应了文档media controller centric的定位。平台驱动与设备树匹配rkcif-dev.c 中的rkcif_probe()是理解整个驱动的入口其关键流程为通过of_device_get_match_data()取得rkcif_match_data区分 PX30/RK3568/RK3588 三个变体devm_platform_ioremap_resource()映射寄存器基址platform_get_irq()devm_request_irq()注册中断中断处理函数rkcif_isr()将中断同时分发给 DVP 与 MIPI 两个捕获通路见 rkcif-dev.c按 match data 获取时钟devm_clk_bulk_get与复位控制devm_reset_control_array_get_exclusive初始化并注册media_device与v4l2_device随后rkcif_register()依次调用rkcif_dvp_register()与rkcif_mipi_register()——二者返回-ENODEV时被容忍从而优雅支持只有 DVPPX30或只有 MIPIRK3588的变体通过v4l2_async_nf_*注册异步通知器等待外部视频源如 imx415、it6801subdevice 完成异步绑定rkcif_notifier_bound()中调用v4l2_create_fwnode_links_to_pad()建立从视频源到 INTERFACE sink pad 的媒体链路。电源管理方面rkcif-dev.cruntime_suspend时会先reset_control_assert/deassert复位 CIF注释明确指出该复位会同时复位 IOMMU因此不能在 resume 阶段执行再关闭时钟runtime_resume则重新使能时钟。INTERFACE/CROP 块一个 V4L2 subdevice 的内部逻辑每个 INTERFACE 块在驱动中对应一个rkcif_interface结构见 rkcif-common.h它内嵌struct v4l2_subdev sd、两个媒体 padsink/source由rkcif_interface_pad_index枚举定义并且持有streams[RKCIF_ID_MAX]数组——即最多四个rkcif_stream正好对应文档所说的每个 INTERFACE 块支持四条流。rkcif-interface.c 中的set_fmt回调体现了 CROP 块的核心行为source pad 上的格式永远与 sink pad 保持一致if (format-pad RKCIF_IF_PAD_SRC) return v4l2_subdev_get_fmt(...)设置 sink pad 格式后驱动会把该格式传播propagate到 source pad每次设置格式时CROP 矩形被重置为全尺寸crop-left/top 0width/height sink 尺寸。而get_sel/set_sel回调rkcif-interface.c则实现了V4L2_SEL_TGT_CROP等目标的选择处理CROP_DEFAULT与CROP_BOUNDS返回输入全尺寸CROP返回当前裁剪矩形。这意味着用户可以通过 subdev 的 selection ioctl 在 INTERFACE 块内完成图像的裁剪配置。流管理与 ping-pong 双缓冲rkcif_stream见 rkcif-common.h是每个 video device 背后的核心结构其中两个字段直接对应文档提到的 ping-pong 机制/* in ping-pong mode, two buffers can be provided to the HW */ struct rkcif_buffer *buffers[2]; int frame_idx; int frame_phase;以及/* in case of no available buffer, HW can write to the dummy buffer */ struct rkcif_dummy_buffer dummy;rkcif-stream.c 中的rkcif_stream_pingpong()是 ping-pong 模式的核心实现其工作方式为中断到来时处理当前frame_phase指向的 buffer若非 dummy buffer则调用rkcif_stream_complete_buffer()将其标记为VB2_BUF_STATE_DONE并递增frame_idx帧序号从驱动内部队列driver_queue弹出下一个可用 buffer 填入当前 phase若队列为空则回退到 dummy buffer并打印 no buffer available, frame will be dropped该帧被丢弃硬件继续写入不中断调用queue_buffer()把新 buffer 地址写入硬件寄存器翻转frame_phase 1 - frame_phase硬件在下一帧写入另一块 buffer。这种两块 buffer 交替 dummy 兜底的设计保证了硬件 DMA 永远不会因用户态来不及提交 buffer 而写到非法地址——这是文档所述double-buffering mechanism called ping-pong mode的完整工程化实现。流启动时rkcif_stream_start_streamingrkcif-stream.c会依次启动媒体管道video_device_pipeline_start、唤醒运行时 PM、初始化 buffers、调用各通路的start_streaming钩子最后通过v4l2_subdev_enable_streams()按BIT_ULL(stream-id)掩码启用对应流。流格式方面rkcif-stream.c 定义了统一的尺寸约束宽度与高度均限制在64 到 8192 像素之间CIF_MIN_WIDTH/HEIGHT 64、CIF_MAX_WIDTH/HEIGHT 8192CIF_REQ_BUFS_MIN为 1。缓冲管理使用videobuf2的dma-contig内存模型并在rkcif_stream_prepare_buffer()中为非多平面non-mplane格式自动推导 Y/UV 平面地址。如何在内核中启用与查看 rkcif编译与加载在内核配置中启用CONFIG_VIDEO_ROCKCHIP_CIFDevice Drivers → Multimedia support → Media platform devices下可编译为模块rockchip-cifmodprobe rockchip-cif加载或编入内核该驱动仅在ARCH_ROCKCHIP或开启COMPILE_TEST时参与构建运行时依赖设备树节点中的 compatible 字符串完成匹配rockchip,px30-vip、rockchip,rk3568-vicap、rockchip,rk3588-vicap见 rkcif-dev.c。观察设备拓扑驱动成功 probe 并完成异步绑定后会在/dev下呈现与文档拓扑一一对应的节点具体编号取决于系统已有设备上述/dev/videoX编号来自 dot 图中的示例每个 INTERFACE/CROP 块、每个 MIPI CSI-2 receiver 各对应一个/dev/v4l-subdevX每个 DMA 引擎对应一个/dev/videoX。由于驱动是媒体控制器中心的各实体之间通过媒体链路连接例如视频源 →dw-mipi-csi2rx→rkcif-mipi2→rkcif-mipi2-id0。在多流变体RK3568/RK3588上DVP 或 MIPI 的id1/id2/id3等额外流需要先建立并启用对应的媒体链路再通过标准 V4L2 接口如VIDIOC_STREAMON启动采集每条流可以承载一路独立的视频数据例如 MIPI CSI-2 的不同 Virtual Channel。结语从只有一个 DVP 的 PX30 VIP到一个 DVP 六个 MIPI CSI-2 接口、每个接口四条流的 RK3588 VICAPRockchip CIF 家族展示了同一个rkcif驱动如何用match data 通用构建块的方式优雅覆盖多种硬件组合。理解文档中给出的 subdevice/video device 命名规律rkcif-接口-id流号再结合 rkcif-common.h 中的枚举与 rkcif-stream.c 中的 ping-pong 实现你就能在内核源码层面完整还原任意 Rockchip 视频采集链路的数据从哪来、经谁裁剪、由哪个 DMA 引擎送往哪块内存。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价