RK628 Linux 内核驱动开发指南
基于源码分析 | Kernel 6.12 | 作者
1. 项目概述
RK628 是 Rockchip 推出的一款多功能显示桥接芯片(Bridge IC),核心功能是将 HDMI 输入信号转换为多种输出格式,广泛应用于 IPTV 机顶盒、中屏显示、视频采集等场景。
主要特性
- ✅ HDMI 接收(HDMI 1.4 / HDMI 2.0),支持 HDCP
- ✅ MIPI CSI-2 TX 输出(1~4 lane),用于视频采集
- ✅ MIPI DSI TX 输出,用于驱动 MIPI 屏
- ✅ BT1120 输出,用于连接外部视频处理器
- ✅ 支持 RGB / YUV422 / YUV444 多种色彩空间
- ✅ 内置 Scaler(缩放器),支持分辨率转换
- ✅ 内置 CSC(色彩空间转换),RGB ↔ YUV 互转
- ✅ 内置 CRU(时钟复位单元),可独立生成所需时钟
- ✅ MIPI D-PHY TX/RX,支持双通道 MIPI
- ✅ 支持 EDID 读取和 HDCP 密钥管理
- ✅ CEC(Consumer Electronics Control)支持
- ✅ I2C 控制接口,DebugFS 调试支持
芯片版本
| 版本 | 枚举值 | 说明 |
|---|---|---|
| RK628D | RK628D_VERSION |
基础版本 |
| RK628F | RK628F_VERSION |
增强版本,支持 HDMI 2.0 |
驱动模块划分
驱动在内核中编译为三个独立的可加载模块:
| 模块名 | Kconfig 选项 | 编译产物 | 功能 |
|---|---|---|---|
| video-rk628 | CONFIG_VIDEO_RK628 |
video-rk628.ko |
核心驱动(GRF/CRU/PHY/Scaler/DSI 等) |
| rk628-csi | CONFIG_VIDEO_RK628_CSI |
rk628-csi.ko |
HDMI → MIPI CSI-2 桥接(V4L2 subdev) |
| rk628-bt1120 | CONFIG_VIDEO_RK628_BT1120 |
rk628-bt1120.ko |
HDMI → BT1120 桥接(V4L2 subdev) |
2. 目录结构
drivers/media/i2c/rk628/
├── Makefile # 模块编译定义(3 个 ko 目标)
├── Kconfig # 内核配置选项
├── rk628.c # 核心驱动:I2C 注册、regmap、debugfs、scaler
├── rk628.h # 核心头文件:寄存器定义、结构体、API 声明
├── rk628_hdmirx.c # HDMI RX 子模块:HDMI 接收、EDID、HDCP、音频
├── rk628_hdmirx.h # HDMI RX 寄存器定义和数据结构
├── rk628_csi_v4l2.c # CSI V4L2 子设备:HDMI→MIPI CSI-2 桥接
├── rk628_csi.h # CSI TX 寄存器定义
├── rk628_bt1120_v4l2.c # BT1120 V4L2 子设备:HDMI→BT1120 桥接
├── rk628_dsi.c # MIPI DSI TX 控制器
├── rk628_dsi.h # DSI 寄存器定义
├── rk628_mipi_dphy.c # MIPI D-PHY 配置(HS 频率范围初始化)
├── rk628_mipi_dphy.h # D-PHY 测试接口定义
├── rk628_cru.c # CRU(时钟复位单元)驱动
├── rk628_cru.h # CRU 寄存器定义(PLL/Gate/SoftRST)
├── rk628_combrxphy.c # Combo PHY RX 驱动(接收端物理层)
├── rk628_combrxphy.h # Combo PHY RX 寄存器定义
├── rk628_combtxphy.c # Combo PHY TX 驱动(发送端物理层)
├── rk628_combtxphy.h # Combo PHY TX 寄存器定义
├── rk628_post_process.c # 后处理:CSC 色彩转换、测试图案
└── rk628_post_process.h # 后处理接口声明
3. 架构设计
整体数据流
┌──────────────────────────────────────────────────────────────┐
│ RK628 芯片 │
│ │
│ ┌─────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ HDMI RX │───▶│ GRF + │───▶│ 后处理模块 │ │
│ │ (输入) │ │ Scaler + │ │ (CSC / 缩放) │ │
│ └─────────┘ │ CSC │ └───────┬──────────┘ │
│ │ │ │ │ │
│ ┌────┴───┐ │ ┌────────┐ │ ┌───────┴──────────┐ │
│ │ComboRX │ │ │ CRU │ │ │ 输出路径选择 │ │
│ │PHY │ │ │ (时钟) │ │ └──┬────┬────┬────┘ │
│ └────────┘ │ └────────┘ │ │ │ │ │
│ └──────────────┘ ┌────┴┐ ┌┴───┐ ┌┴────┐ │
│ │ CSI │ │DSI │ │BT │ │
│ │ TX │ │ TX │ │1120 │ │
│ └──┬──┘ └─┬──┘ └──┬──┘ │
│ │ │ │ │
│ ┌─────────────┐ ┌───────┘ │ │ │
│ │ MIPI D-PHY │ ┌──────────────┘ │ │
│ │ TX + RX │ │ ComboTX PHY │ │
│ └─────────────┘ └─────────────────────┘ │
│ └──┘
└──────────────────────────────────────────────────────────────┘
I2C 寄存器分区
RK628 通过 I2C 总线控制,内部寄存器空间按功能分区,驱动使用 regmap 框架统一管理:
| 分区 ID | 名称 | 基地址 | 说明 |
|---|---|---|---|
RK628_DEV_GRF |
grf | 0x0000xxxx |
通用寄存器文件(系统控制、Scaler、LVDS、中断等) |
RK628_DEV_COMBRXPHY |
combrxphy | 0x0006xxxx |
Combo PHY 接收端 |
RK628_DEV_HDMIRX |
hdmirx | 0x0003xxxx |
HDMI 接收控制器 |
RK628_DEV_CSI |
csi | 0x0004xxxx |
MIPI CSI TX 控制器 |
RK628_DEV_CSI1 |
csi1 | 0x0004xxxx |
第二路 MIPI CSI TX |
RK628_DEV_DSI0 |
dsi0 | 0x0005xxxx |
MIPI DSI TX 控制器 0 |
RK628_DEV_DSI1 |
dsi1 | 0x0006xxxx |
MIPI DSI TX 控制器 1 |
RK628_DEV_COMBTXPHY |
combtxphy | --- | Combo PHY 发送端 |
RK628_DEV_ADAPTER |
adapter | 0x000axxxx |
EDID / HDCP Key 存储 |
RK628_DEV_CRU |
cru | --- | 时钟复位单元 |
寄存器访问通过寄存器高字节自动路由到对应分区,无需手动切换 bank。
4. 核心模块详解
4.1 核心框架(rk628.c / rk628.h)
入口函数 :rk628_i2c_register(struct i2c_client *client)
负责:
- 通过
devm_regmap_init_i2c()为所有寄存器分区初始化 regmap 实例 - 初始化
rst_lock互斥锁(保护 HDMI RX 寄存器访问) - 创建 DebugFS 调试节点
关键 API:
c
// I2C 寄存器读写(根据寄存器地址高字节自动路由分区)
int rk628_media_i2c_write(struct rk628 *rk628, u32 reg, u32 val);
int rk628_media_i2c_read(struct rk628 *rk628, u32 reg, u32 *val);
int rk628_media_i2c_update_bits(struct rk628 *rk628, u32 reg, u32 mask, u32 val);
// 便捷封装(内联函数)
static inline int rk628_i2c_write(struct rk628 *rk628, u32 reg, u32 val);
static inline int rk628_i2c_read(struct rk628 *rk628, u32 reg, u32 *val);
核心数据结构:
c
struct rk628 {
struct device *dev;
struct i2c_client *client;
struct regmap *regmap[RK628_DEV_MAX]; // 各分区 regmap 实例
u8 version; // RK628D / RK628F
u8 color_format; // 色彩格式
u8 color_range; // 色彩范围(full/limited)
u8 color_space; // 色彩空间
int dvi_mode; // DVI/HDMI 模式
int vic; // Video Identification Code
int tx_mode; // 发送模式(CSI/DSI/BT1120)
bool dual_mipi; // 双通道 MIPI
bool hdr_support; // HDR 支持
struct dentry *debug_dir;
// ... 更多字段
};
4.2 HDMI RX 子模块(rk628_hdmirx.c / rk628_hdmirx.h)
功能:接收 HDMI 信号,解析音视频数据。
| 子功能 | 说明 |
|---|---|
| TMDS 解码 | 解析 HDMI/DVI 的 TMDS 编码信号 |
| EDID 管理 | 读取/写入 EDID 数据(EDID_BASE = 0x000a0000) |
| HDCP | 支持 HDCP 密钥存储和认证(HDCP_KEY_BASE = 0x000a8000) |
| 音频提取 | 支持 I2S 音频输出,含 FIFO 管理和采样率检测 |
| CEC | 消费电子控制协议 |
| 热插拔检测 | HPD(Hot Plug Detect)GPIO 和中断处理 |
| HDMI 2.0 | 支持 SCDC(Status and Control Data Channel) |
色彩格式枚举:
c
enum hdmirx_pix_fmt {
HDMIRX_RGB888 = 0,
HDMIRX_YUV422 = 1,
HDMIRX_YUV444 = 2,
HDMIRX_YUV420 = 3,
};
4.3 MIPI CSI-2 输出(rk628_csi_v4l2.c / rk628_csi.h)
功能:将 HDMI 接收的视频数据打包为 MIPI CSI-2 协议输出。
实现为 V4L2 subdev,向上对接 CIF(Camera Interface)控制器。
关键配置:
| 寄存器 | 说明 |
|---|---|
CSITX_CSITX_EN |
CSI TX 使能,配置 lane 数、DPHY 使能 |
CSITX_VOP_PATH_CTRL |
像素格式、数据类型、WC 用户自定义 |
CSITX_VOP_FILTER_CTRL |
VOP 滤波器控制 |
CSITX_SYS_CTRL2 |
VSYNC 使能、帧使能、非连续模式 |
支持的像素格式:RGB888、YUV422(多种排列)、RAW 等。
4.4 MIPI DSI 输出(rk628_dsi.c / rk628_dsi.h)
功能:通过 MIPI DSI 协议驱动 MIPI 屏幕,支持两路独立 DSI 控制器(DSI0/DSI1)。
| 配置项 | 说明 |
|---|---|
DSI_DPI_COLOR_CODING |
输入色彩编码(16/18/24 bit) |
DSI_VID_MODE_CFG |
视频模式配置(同步脉冲/事件/突发模式) |
DSI_VID_PKT_SIZE |
视频包大小 |
DSI_CLKMGR_CFG |
时钟分频配置 |
支持 命令模式 和 视频模式 两种 DSI 工作模式。
4.5 BT1120 输出(rk628_bt1120_v4l2.c)
功能:将 HDMI 视频以 BT1120 并行数字接口格式输出,同样实现为 V4L2 subdev。
适用于连接外部视频处理器或 FPGA。
4.6 后处理模块(rk628_post_process.c / rk628_post_process.h)
功能:
-
CSC(Color Space Conversion):RGB ↔ YUV 色彩空间转换
cvoid rk628_post_process_csc_en(struct rk628 *rk628, bool input_full_range, bool output_full_range); void rk628_post_process_csc_dis(struct rk628 *rk628); u8 rk628_csc_color_space_convert(u8 in_color_space, u8 format); -
Scaler(缩放) :在
rk628.c中实现,支持水平/垂直缩放- 缩放因子精度 14-bit
- 支持缩放因子 ≤ 2 和 > 2 两种算法
- 自动计算帧起始位置以匹配源端时序
-
测试图案:通过 DebugFS 控制输出彩色条纹等测试图案
4.7 CRU 时钟模块(rk628_cru.c / rk628_cru.h)
功能:管理 RK628 内部 PLL 和时钟分频。
| 时钟 | 说明 |
|---|---|
| CPLL | 通用 PLL |
| GPLL | 通用 PLL |
| APLL | 音频 PLL |
通过 CRU_CLKSEL_CON、CRU_GATE_CON、CRU_SOFTRST_CON 寄存器组控制。
4.8 MIPI D-PHY(rk628_mipi_dphy.c / rk628_mipi_dphy.h)
功能:配置 MIPI D-PHY 的 HS 频率范围参数。
c
// 核心接口
void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id);
int rk628_mipi_dphy_reset_assert(struct rk628 *rk628);
int rk628_mipi_dphy_reset_deassert(struct rk628 *rk628);
// D-PHY 测试接口(Test Code 读写)
u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id);
u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id);
5. 构建与编译
内核配置
在 Kernel 6.12 的 make menuconfig 中:
Device Drivers --->
Multimedia support --->
Media ancillary drivers --->
I2C Encoders, decoders, sensors and other helper chips --->
<M> Rockchip RK628_CSI decoder
<M> Rockchip RK628_BT1120 decoder
或直接修改 .config:
bash
CONFIG_VIDEO_RK628=m
CONFIG_VIDEO_RK628_CSI=m
CONFIG_VIDEO_RK628_BT1120=m
编译
bash
# 编译为模块
make M=drivers/media/i2c/rk628
# 或完整内核编译
make -j$(nproc)
编译依赖:
CONFIG_I2C=y
CONFIG_REGMAP=y
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_CEC_CORE=y
CONFIG_HDMI=y
加载模块
bash
# 先加载核心模块
insmod video-rk628.ko
# 再加载具体输出模块(按需)
insmod rk628-csi.ko # HDMI → MIPI CSI-2
insmod rk628-bt1120.ko # HDMI → BT1120
6. DTS 配置
RK628 作为 I2C 设备挂载,典型 DTS 节点:
dts
&i2c1 {
status = "okay";
rk628: rk628@50 {
compatible = "rockchip,rk628";
reg = <0x50>;
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
hdmirx-det-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&rk628_pins>;
/* 端口定义 */
ports {
#address-cells = <1>;
#size-cells = <0>;
/* HDMI RX 输入端口(可选,连接 HDMI 连接器) */
port@0 {
reg = <0>;
rk628_hdmirx_in: endpoint {
remote-endpoint = <&hdmi_con_in>;
};
};
/* CSI TX 输出端口 → CIF/ISP */
port@1 {
reg = <1>;
rk628_csi_out: endpoint {
remote-endpoint = <&cif_in>;
data-lanes = <1 2 3 4>;
clock-lanes = <0>;
};
};
};
};
};
GRF 系统控制寄存器配置(通常在 SoC GRF 中配置):
c
// 输入模式选择
SW_INPUT_MODE(HDMI / BT1120 / RGB / YUV)
// 输出模式选择
SW_OUTPUT_MODE(GVI / LVDS / HDMI / CSI / DSI / BT1120 / RGB / YUV)
7. 调试指南
DebugFS 接口
驱动注册了丰富的 DebugFS 节点,路径为 /sys/kernel/debug/rk628/<device>/:
/sys/kernel/debug/rk628/<device>/
├── debug # 调试开关(写入 1 开启详细日志)
└── registers/ # 寄存器读写节点
├── grf # GRF 寄存器
├── cru # CRU 寄存器
├── combrxphy # Combo RX PHY 寄存器
├── combtxphy # Combo TX PHY 寄存器
├── hdmirx # HDMI RX 寄存器
├── dsi0 # DSI0 寄存器
├── dsi1 # DSI1 寄存器
└── csi # CSI 寄存器
读取寄存器:
bash
cat /sys/kernel/debug/rk628/<device>/registers/grf
写入寄存器:
bash
echo "0x0010 0x00000005" > /sys/kernel/debug/rk628/<device>/registers/grf
# 格式: addr(十六进制) val(十六进制)
开启调试日志:
bash
echo 1 > /sys/kernel/debug/rk628/<device>/debug
# 查看内核日志
cat /proc/kmsg | grep rk628
内核模块参数
bash
# CSI 模块调试级别(0-3)
insmod rk628-csi.ko debug=3
# BT1120 模块调试级别
insmod rk628-bt1120.ko debug=3
常用调试方法
| 方法 | 命令/说明 |
|---|---|
| 查看模块加载 | `lsmod |
| 查看 I2C 设备 | i2cdetect -y <bus> |
| 查看 V4L2 设备 | v4l2-ctl --list-devices |
| 查看支持的时序 | v4l2-ctl -d /dev/video0 --list-dv-timings |
| 寄存器 dump | DebugFS registers/ 节点 |
| 测试图案输出 | echo 1 > /sys/kernel/debug/rk628/<dev>/pattern |
8. 常见问题 FAQ
Q: insmod video-rk628.ko 后无反应?
A: 检查 DTS 中 I2C 地址是否匹配(默认 0x50),使用 i2cdetect 确认设备在总线上可见。
Q: HDMI 接入后无画面输出?
A: 1) 检查 HPD GPIO 是否正确配置;2) 检查 GRF 的 SW_INPUT_MODE 和 SW_OUTPUT_MODE 是否匹配;3) 开启 debug 日志查看 HDMI RX 状态。
Q: CSI 输出花屏或色彩异常?
A: 1) 确认 CSI lane 数配置正确;2) 检查 CSITX_VOP_PATH_CTRL 的像素格式是否与实际色彩格式一致;3) 检查 CSC 是否正确启用。
Q: 缩放后画面撕裂?
A: Scaler 的帧起始计算依赖精确的源端/目标端 pixelclock,确认两端 videomode 参数配置正确。查看 dsp_frame_vst 和 dsp_frame_hst 的调试日志。
Q: 如何确认芯片版本?
A: 驱动启动时调用 rk628_version_parse() 读取 GRF_SOC_VERSION 寄存器,版本信息会打印在内核日志中。
Q: 双通道 MIPI 如何配置?
A: 设置 dual_mipi = true,并确保 DSI0 和 DSI1 均已配置,GRF 中启用 GRF_DPHY_CH1_EN。
9. 版本与作者
| 项目 | 信息 |
|---|---|
| 芯片 | Rockchip RK628 |
| 内核版本 | Linux 6.12 |
| 许可证 | GPL-2.0 |