瑞芯微ISP内核驱动深度解析|RKISP39从架构到Probe初始化全流程(上篇)

RKISP内核驱动的解析与实战系列文章,为了方便读者更清晰分模块了解,此篇文章将分为上、中、下三篇发布,本篇为上篇。

本篇将以RK3576(ISP39)+Linux Kernel6.1的完整源码为基础,从驱动架构全景、设备初始化Probe流程、Media子设备拓扑、中断处理以及ISP39专属硬件特性等维度,全方位拆解RKISP整套驱动逻辑。如果你正在从事具身智能、机器人视觉、自动驾驶、无人机感知或工业视觉检测等领域的嵌入式开发,这篇文章将是你的绝佳参考。

一、摄像头链路配置参考

RK3576摄像头链路的配置原理大体与RK3588类似,只是节点下标与硬件对应不同,此处提供RK3576的链路图,其余参考RK3588即可。

  • RK3576 MIPI CSI 4lane场景的数据链路图
  • RK3576拆分2lane场景的数据链路图
  • RK3576 DVP数据链路图

适用平台:RK3576/ISP39内核版本:Kernel6.1

源码路径:drivers/media/platform/rockchip/isp/

配套代码目录:kernel-6.1/drivers/media/platform/rockchip/isp/

驱动版本:v2.6.0+(该版本首次完整支持ISP39硬件)

二、驱动架构全景

  • 整体分层结构

RKISP驱动遵循V4L2标准分层设计,从用户态到硬件寄存器分为五层,层级清晰解耦:

复制代码
┌──────────────────────────────────────────────────────────┐│                    用户态层 (Camera HAL3)                 │├──────────────────────────────────────────────────────────┤│              /dev/video*  /dev/v4l2-subdev* 设备节点     │├──────────────────────────────────────────────────────────┤│              V4L2 / Media Controller 媒体框架层          │├──────────────────────────────────────────────────────────┤│                    rkisp 驱动总入口层                     ││              (dev.c / rkisp.c / hw.c / regs.c)            │├─────────────┬────────────── ┬─────────────────────────────┤│  rkisp.ko   │   捕获通道     │      3A / 参数管理          ││  主驱动模块  │ capture.c     │  isp_params.c / stats.c     ││             │ capture_v39.c │  isp_params_v39.c           ││             │               │  isp_stats_v39.c            │├─────────────┴────────────── ┴─────────────────────────────┤│   CSI-2 接收 │   Bridge桥接  │   IOMMU    │  DMA Rx   ││   csi.c      │   bridge.c   │  rkisp_mmu │  dmarx.c  │├───────────── ┴──────────────┴────────────┴──────────┤│                    ISP39 硬件寄存器底层               ││              (regs.c / regs_v3x.h)                  │└─────────────────────────────────────────────────────┘
  • ISP硬件版本枚举定义

在驱动头文件common.h中定义了全系列ISP硬件版本枚举,RK3576平台专属ISP39对应宏ISP_V39 = 0xa0:

复制代码
// common.h
enum rkisp_isp_ver {
    ISP_V10  = 0x00,
    ISP_V12  = 0x20,
    ISP_V13  = 0x30,
    ISP_V20  = 0x40,
    ISP_V21  = 0x50,
    ISP_V30  = 0x60,
    ISP_V32  = 0x70,
    ISP_V32_L= 0x80,
    ISP_V33  = 0x90,
    ISP_V39  = 0xa0,   // RK3576平台专用ISP
    ISP_V35  = 0xb0,
};
  • Media Controller媒体拓扑图

RKISP完全基于V4L2 Media Controller框架实现,注册大量v4l2_subdev子设备与video输出节点,完整数据流链路如下:

复制代码
┌──────────────┐     ┌──────────────┐     ┌──────────────┐│  Sensor      │     │  MIPI D-PHY  │     │  CSI Subdev  ││ 图像传感器    │────▶MIPI物理层──────▶  rkisp-csi子设备 │└──────────────┘     └──────────────┘     └──────┬───────┘                                                 │                                                 ▼┌───────────────────────────────────────────────────────┐│              ISP Subdev (rkisp-isp-subdev)             ││    端口:SINK(0)输入 | SINK_PARAMS(1)参数 | SOURCE_PATH(2)图像输出│                                           │ SOURCE_STATS(3)3A统计输出└──┬──────────────┬──────────────┬──────────┴───────────┘   │              │              │   ▼              ▼              ▼┌────────┐  ┌──────────┐  ┌───────────┐│ MP     │  │ SP       │  │ LDC       ││ mainpath│  │ selfpath │  │ ldcpath   ││ /dev/  │  │ /dev/    │  │ /dev/     ││ video0 │  │ video1   │  │ video2    │└────────┘  └──────────┘  └───────────┘┌──────────┐  ┌───────────┐│ params   │  │ stats     ││ 参数下发  │  │ 3A统计上报 │└──────────┘  └───────────┘

各video设备节点功能对照表(定义于capture.h):

|-------------------|------------------|--------------------------|
| 宏定义 | 设备节点名称 | 核心用途 |
| MP_VDEV_NAME | rkisp_mainpath | 主输出通道,支持YUV/Raw原始图像输出 |
| SP_VDEV_NAME | rkisp_selfpath | 自缩放通道,输出小尺寸预览图 |
| LDC_VDEV_NAME | rkisp_ldcpath | 镜头畸变校正专用输出通道 |
| FBC_VDEV_NAME | rkisp_fbcpath | ISP39新增,图像压缩输出通道 |
| BP_VDEV_NAME | rkisp_bypasspath | Bypass直通通道,输出未经ISP处理原始数据 |
| DMATRX0_VDEV_NAME | rkisp_rawwr0~3 | HDR多路DMA原始数据写入通道 |

设备节点可在系统路径/sys/class/video4linux/下查看,全部挂载至media graph媒体拓扑链路中。

三、Probe设备上电初始化全流程****

  • 平台设备匹配与DTS节点配置

驱动入口函数为dev.c内rkisp_plat_probe(),通过DTS中compatible字符串匹配硬件平台:

复制代码
// hw.c
{ .compatible = "rockchip,rk3576-rkisp", .data = &rk3576_isp_match_data },

RK3576完整ISP设备树节点(rk3576.dtsi:3302):

复制代码
rkisp: isp@27c00000 {
    compatible = "rockchip,rk3576-rkisp";
    reg = <0x0 0x27c00000 0x0 0x7f00>;
    interrupts = <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>,  // mipi_irq
                 <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH>,  // mi_irq
                 <GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH>;  // isp_irq
    interrupt-names = "mipi_irq", "mi_irq", "isp_irq";
    clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>,
             <&cru CLK_ISP_CORE>, <&cru CLK_ISP_CORE_MARVIN>,
             <&cru CLK_ISP_CORE_VICAP>;
    clock-names = "aclk_isp", "hclk_isp",
                  "clk_isp_core", "clk_isp_core_marvin",
                  "clk_isp_core_vicap";
    power-domains = <&power RK3576_PD_VI>;
    iommus = <&rkisp_mmu>;
    status = "disabled";
};
  • Probe主函数执行顺序

rkisp_plat_probe()(dev.c:911)从上电到注册完整子设备执行链路:

复制代码
rkisp_plat_probe
├── rkisp_attach_hw()         // 绑定物理硬件设备(hw.c)
│   ├── of_find_device_by_node(hw_node)
│   └── rkisp_hw_probe()      // 硬件底层初始化
├── devm_kzalloc(sw_base)     // 分配软件影子寄存器缓存
├── rkisp_vs_irq_parse()      // 解析VSYNC帧同步中断
├── media_device_init()       // 初始化Media设备框架
├── v4l2_device_register()    // 注册标准V4L2设备
├── pm_runtime_enable()       // 开启电源管理 runtime
├── rkisp_register_platform_subdevs()  // 核心:批量注册所有子设备
│   ├── rkisp_register_isp_subdev()    // ISP核心子设备
│   ├── rkisp_register_csi_subdev()    // CSI MIPI接收子设备
│   ├── rkisp_register_bridge_subdev() // ISP与ISPP桥接子设备
│   ├── rkisp_register_stream_vdevs()  // MP/SP/LDC图像捕获通道
│   │   └── (版本分发) rkisp_register_stream_v39()
│   ├── rkisp_register_dmarx_vdev()    // DMA原始数据写入节点
│   ├── rkisp_register_stats_vdev()    // 3A统计上报节点
│   ├── rkisp_register_params_vdev()   // 3A参数下发节点
│   ├── rkisp_register_luma_vdev()     // 亮度统计通道
│   └── rkisp_register_pdaf_vdev()     // PDAF对焦数据通道(可选)
├── isp_subdev_notifier()     // 异步探测Sensor图像传感器
└── media_device_register()  // 完成Media设备注册
  • 硬件绑定rkisp_attach_hw

该函数建立逻辑驱动与物理ISP硬件的绑定关系,核心硬件结构体rkisp_hw_dev:

复制代码
// hw.c
struct rkisp_hw_dev {
    const struct isp_match_data *match_data;
    struct platform_device *pdev;
    void __iomem *base_addr;
    struct clk *clks[RKISP_MAX_BUS_CLK];
    enum rkisp_isp_ver isp_ver;
    struct rkisp_device *isp[DEV_MAX];    // 最多DEV_MAX个虚拟ISP设备
    int dev_num;
    u32 unite;  // 图像拼接模式:无拼接/双ISP拼接/单通道拼接
    bool is_mmu;
    struct rkisp_monitor monitor;         // 硬件看门狗监控
    // ...
};

RK3576 ISP硬件匹配时钟配置(hw.c:929):

复制代码
static const struct isp_match_data rk3576_isp_match_data = {
    .clks = rk3576_isp_clks,
    .num_clks = ARRAY_SIZE(rk3576_isp_clks),
    .isp_ver = ISP_V39,
    .clk_rate_tbl = rk3576_isp_clk_rate,
    .num_clk_rate_tbl = ARRAY_SIZE(rk3576_isp_clk_rate),
};
static const char * const rk3576_isp_clks[] = {
    "clk_isp_core",
    "aclk_isp",
    "hclk_isp",
    "clk_isp_core_marvin",
    "clk_isp_core_vicap",
};

RK3576 ISP共5路独立时钟域,对比RK3588精简冗余拼接时钟;其中clk_isp_core_marvin、clk_isp_core_vicap为ISP39全新硬件时钟。

  • 多虚拟ISP拓扑(Multi Virtual ISP)

RK3576 DTS定义rkisp_vir0 ~ rkisp_vir5共6路虚拟ISP,全部共享同一块物理ISP硬件,通过rockchip,hw = <&rkisp>绑定物理节点:

复制代码
物理ISP硬件 ──→ rkisp_vir0 ──→ rkisp_vir0_sditf ──→ vpss0_in (ISPP后处理)          │  rkisp_vir1 ──→ rkisp_vir1_sditf ──→ vpss1_in          │  rkisp_vir2 ──→ rkisp_vir2_sditf ──→ vpss2_in          │  ...          └  rkisp_vir5 ──→ rkisp_vir5_sditf ──→ vpss5_in

每一路rkisp_virN通过sditf(子设备接口)桥接对应VPSS图像后处理单元。

多虚拟ISP核心作用 :支持多路Sensor、多规格图像流分时复用单块ISP硬件,由上层AIQ 3A算法做时间片调度,是双摄、多摄方案的核心底层支撑。

四、ISP核心Subdev** 子设备详解**

  • 核心数据结构 rkisp_isp_subdev

该结构体是ISP图像处理管线的逻辑抽象,定义于rkisp.h:136:

复制代码
struct rkisp_isp_subdev {
    struct v4l2_subdev sd;            // 标准V4L2子设备实例
    struct media_pad pads[RKISP_ISP_PAD_MAX]; // 4个媒体端口
    struct v4l2_mbus_framefmt in_frm; // Sensor原始输入图像尺寸
    struct ispsd_in_fmt in_fmt;       // 输入图像格式
    struct v4l2_rect in_crop;         // ISP_ACQ输入裁剪区域
    struct ispsd_out_fmt out_fmt;     // ISP输出图像格式
    struct v4l2_rect out_crop;        // ISP_IS输出稳定裁剪区域
    atomic_t frm_sync_seq;            // 帧同步序列号
};
  • 媒体端口Pad布局与两级裁剪

端口定义

复制代码
enum rkisp_isp_pad {
    RKISP_ISP_PAD_SINK,          // Pad 0:图像输入(CSI/DVP数据源)
    RKISP_ISP_PAD_SINK_PARAMS,   // Pad 1:3A参数下发输入口
    RKISP_ISP_PAD_SOURCE_PATH,   // Pad 2:处理后图像输出(MP/SP/LDC)
    RKISP_ISP_PAD_SOURCE_STATS,  // Pad 3:3A统计数据输出口
    RKISP_ISP_PAD_MAX
};

ISP内部两级裁剪逻辑:

复制代码
+---------------------------------------------------------+| Sensor原始图像 in_frm                                   || +---------------------------------------------------+ || | ISP_ACQ (黑电平校正专用裁剪)                      |   || | in_crop 裁剪有效像素区域                           |   || | +--------------------------------------------+ | || | |    ISP_IS (图像防抖稳定裁剪)                 |    |   || | |    out_crop 最终输出分辨率裁剪                |    |   || | |                                            |    |   || | |  ──→ MP (mainpath) 输出YUV/Raw原图          |    |   || | |  ──→ SP (selfpath) 缩放预览图               |    |   || | |  ──→ LDC (ldcpath) 畸变校正图               |    |   || | +--------------------------------------------+ | || +---------------------------------------------------+ |+---------------------------------------------------------+

ISP_ACQ(in_crop) 从Sensor原始画面截取有效像素,用于黑电平校正BLS、坏点修复DPCC;

SP_IS(out_crop)图像防抖裁剪,裁剪后分辨率直接输出至三路捕获通道。

  • ISP39输入分辨率硬件上限
复制代码
// rkisp.h
#define CIF_ISP_INPUT_W_MAX_V39        4672
#define CIF_ISP_INPUT_H_MAX_V39        3504
#define CIF_ISP_INPUT_W_MAX_V39_UNITE  8192   // 双ISP拼接模式宽
#define CIF_ISP_INPUT_H_MAX_V39_UNITE  6144   // 双ISP拼接模式高

规格总结:单ISP最大支持4672×3504(约1600万像素) ;开启Unite双ISP拼接模式最高支持8192×6144(约5000万像素)

**、CSI-2接收子设备(** csi.c

  • CSI Subdev核心职责

CSI子设备专门管理MIPI CSI-2接收端硬件,核心工作:

1.D-PHY物理层初始化、MIPI Lane通道数量配置;

2.MIPI数据类型(DT)解析(RAW10/RAW12/YUV422等);

3.虚拟通道VC路由分配;

4.MIPI数据包错误检测、异常硬件复位恢复。

CSI设备结构体:

复制代码
// csi.h
struct rkisp_csi_device {
    struct v4l2_subdev sd;
    struct media_pad pads[CSI_PAD_MAX];
    int lanes;              // MIPI通道数量
    u32 datatype;           // MIPI数据类型
    u32 channel;            // MIPI虚拟通道VC
    bool is_csi3;           // CSI-3协议标识
    // ...
};
  • Sensor与CSI链路解析

rkisp_fwnode_parse()(dev.c:690)解析DTS端点MIPI总线配置:

复制代码
static int rkisp_fwnode_parse(struct device *dev,
                   struct v4l2_fwnode_endpoint *vep,
                   struct v4l2_async_subdev *asd)
{
    struct rkisp_async_subdev *rk_asd =
            container_of(asd, struct rkisp_async_subdev, asd);
    // MIPI sensor总线配置由D-PHY层单独处理,此处仅处理并行/BT656
    if (vep->bus_type != V4L2_MBUS_BT656 &&
        vep->bus_type != V4L2_MBUS_PARALLEL)
        return 0;
    rk_asd->mbus.type = vep->bus_type;
    return 0;
}
  • MIPI中断处理逻辑

中断入口rkisp_mipi_v3x_isr():

1.解析phy锁失、溢出、数据包校验错误等状态位;

2.错误计数累计超过RKISP_CONTI_ERR_MAX (50)自动复位MIPI硬件;

3.向上层上报V4L2_EVENT_FRAME_SYNC帧同步事件,供给3A算法使

至此,上篇内容告一段落。我们从驱动架构全景出发,依次剖析了摄像头链路配置、Probe初始化流程、ISP 核心Subdev子设备以及CSI-2接收模块,为理解RKISP驱动奠定了坚实基础。

相关推荐
有续技术1 小时前
三菱 (Mitsubishi) 机床 设置查看 IP 地址
linux·服务器·网络
yagami_gagami1 小时前
第四届黄河流域公安院校电子物证个人赛服务器取证
linux·服务器·网络·mysql·安全·docker·llama
邪修king2 小时前
Re:Linux系统篇(七) 开发工具篇 Chapter3:Makefile 从入门到精通 —— 依赖关系、伪目标、栈式推导与自动化构建全解
linux·运维·服务器·vim
Funing72 小时前
系列一:STM32 外设初始化
stm32·单片机·嵌入式硬件
bosins2 小时前
Ubuntu 日常最常用的文件操作场景和对应指令
linux·服务器·ubuntu
风曦Kisaki2 小时前
Kubernetes(K8s)笔记Day07: StatefulSet 有状态控制器详解与使用案例
linux·docker·云原生·容器·kubernetes
不相心 -w-2 小时前
Cmake的基础用法
linux·开发语言·c++
深爱水瓶 血影S狂风2 小时前
Linux.NET学习手记(2)
linux·学习·.net
sg_knight3 小时前
Codex CLI 安装全攻略:macOS / Linux / Windows(WSL2)三端实战
linux·windows·macos·openai·ai编程·coding·codex