Linux 下的许多驱动框架其实都挺复杂,大多都是许多国内外的牛人经过多年的完善而积累下来的代码。
学习驱动开发需要找准自己的定位,先全局把握再适当地去填充细节,不要总想着深入到驱动框架里,站在一个使用者的角度去思考如何应用这些驱动框架或许会有更好的效果。
这里我是以一个菜鸟的身份记录下自己的一些想法和学习心得,欢迎纠正我。
一、基础概念
1. Linux 的 2 种显示方案
包括:
FBDEV: Framebuffer Device
DRM/KMS: Direct Rendering Manager / Kernel Mode Setting
它们有什么区别?
FBDEV:
-
传统的显示框架;
简单,但是只能提供最基础的显示功能;
无法满足当前上层应用和底层硬件的显示需求;
DRM/KMS:
-
目前主流的显示方案;
为了适应当前日益更新的显示硬件;
软件上能支持更多高级的控制和特性;
2. DRM/KMS 基础概念
DRM subsystem 图:
虽然经常用 DRM/KMS 来指代整个 DRM subsystem,但是 KMS 和 DRM driver 只是 整个 DRM subsystem 的其中 2 个部分。
KMS (Kernel Mode Setting) 是内核提供给应用层的 DRM API 的其中一部分,应用层一般通过 libdrm 来访问这些 API。
对于驱动工程师而言,重点关注 DRM driver,这里负责使能 Display engine,可以理解为加强版的 FBDEV。
KMS 里的几个重要组件:
Planes:图层,例如在 rockchip 平台里对应 SOC 内部 VOP 模块的 win 图层;
CRTC:显示控制器,例如在 rockchip 平台里对应 SOC 内部的 VOP 模块;
Encoder:输出转换器,指 RGB、LVDS、DSI、eDP、HDMI、CVBS、VGA 等显示接口;
Connector:连接器,指 encoder 和 panel 之间交互的接口部分;
Bridge:桥接设备,一般用于注册 encoder 后面另外再接的转换芯片,如 DSI2HDMI 转换芯片;
Panel:泛指屏,各种 LCD、HDMI 等显示设备的抽象;
这些组件组合成 display pipeline:
3. 驱动视角看 DRM/KMS
下面以 Allwinner 芯片的 DRM driver 为例进行展示。
DRM subsystem:
这里为了便于理解,将 DRM DSI Core / DRM Panel Core / DRM Bridge Core 从 DRM Core 里单独划分出来了,但是其实它们都属于 DRM Core。
DRM driver:
二、了解硬件信息
1. 查阅芯片手册
Rockchip 平台的 LCD Controller 称为 VOP(Video Output Processor),芯片中一般集 成 1~2 个 VOP。只有支持两个 VOP 的芯片,才能支持双屏异显。
RK3399 有 2 个 VOP:
Video Output Processor(VOP_BIG)
Video Output Processor(VOP_LIT)
支持的显示接口:
One or Two MIPI-DSI port
One eDP port
One DP port
One HDMI port
2. 确定单板的显示接口
NanoPC T4:
LCD Interface: 一个eDP 1.3(4 线,10.8Gbps),一个或2个4线 MIPI-DSI;
DP on Type-C: DisplayPort 1.2 Alt Mode on USB Type-C;
HDMI: HDMI 2.0a,支持4K@60Hz显示,支持HDCP 1.4/2.2;
驱动工程师的职责:根据上层业务的需求,使能连接在上述接口上的各种 Panel,包括单独使能某个屏幕、双屏异显、双屏同显等。
三、查看单板的设备树
下面是 NanoPC-T4 设备树里和 display 相关的信息。
1. 相关节点及其状态
2. 各节点的作用
display-subsystem:
配置 Rockchip 的 display engine;
通过 route 表将各组件(plane / crct / encoder / connector) 关联在一起,以便对应的驱动构建出 display pipe;
vopl: vop@ff8f0000:
配置 VOP little;
子节点 port 里有 5 个 endpoint,名字分别为 vopl_out_dsi / vopl_out_edp 等,它们是数据输出端,即 output endpoint;
每个 endpoint 都会连接到某个 remote-endpoint,VOP 的 remote-endpoint 连接的就是各种显示 Encoder的 endpoint,例如 vopl_out_dsi ---> dsi_in_vopl;
vopb: vop@ff900000:
省略
edp: edp@ff970000:
配置 edp 控制器,大致包括基地址、中断、时钟、子节点 port;
2 个 input endpoint,分别连接到 VOPL 和 VOPB;
1 个 output endpoint 连接到了 epd panel 上;
有 3 条连接:
-
vopb_out_edp ---> edp_in_vopb
vopl_out_edp ---> edp_in_vopl
edp_out ---> edp_panel
panel: edp-panel:
配置某一款具体的 edp 屏;
有 1 条连接:
-
edp_out ---> edp_panel
hdmi: hdmi@ff940000:
配置 hdmi 控制器,大致包括引脚、基地址、中断、时钟、子节点 port;
有 2 条连接:
-
vopb_out_hdmi ---> hdmi_in_vopb
vopl_out_hdmi ---> hdmi_in_vopl
dsi: dsi@ff960000 dsi1: dsi@ff968000:
配置 mipi dsi,类似 edp / hdmi;
mipi_dphy_tx1rx1: mipi-dphy-tx1rx1@ff968000:
配置 mipi dphy;
四、查看 Rockchip 的 DRM Driver
1. 驱动路径
功能 | 驱动路径 |
---|---|
DRM master device driver | drivers/gpu/drm/rockchip/rockchip_drm_drv.c |
Framebuffer driver | drivers/gpu/drm/rockchip/rockchip_drm_fb.c drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c |
GEM Driver | drivers/gpu/drm/rockchip/rockchip_drm_gem.c |
VOP Driver | drivers/gpu/drm/rockchip/rockchip_drm_vop.c drivers/gpu/drm/rockchip/rockchip_vop_reg.c |
LVDS Driver | drivers/gpu/drm/rockchip/rockchip_lvds.c drivers/phy/rockchip/phy-rockchip-inno-video-phy.c |
RGA Ddriver | drivers/gpu/drm/rockchip/rockchip_drm_rga.c |
MIPI Driver | drivers/gpu/drm/rockchip/dw-mipi-dsi.c |
HDMI Driver | drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c drivers/gpu/drm/bridge/dw-hdmi.c |
inno HDMI Driver | drivers/gpu/drm/rockchip/inno_hdmi.c drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c |
eDP Driver | drivers/gpu/drm/rockchip/analogix_dp-rockchip.c drivers/gpu/drm/bridge/analogix/analogix_dp_core.c drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c drivers/phy/rockchip/phy-rockchip-dp.c |
DP Driver | drivers/gpu/drm/rockchip/cdn-dp-core.c drivers/gpu/drm/rockchip/cdn-dp-reg.c |
TVE/CVBS Driver | drivers/gpu/drm/rockchip/rockchip_drm_tve.c |
2. Rockchip DRM driver 的 probe 流程
这张图是 Rockchip 官方提供的,非常好的一张图。
有了这张图相当于有了一张源码分析的地图,后续我们可以参考它来进行更细致地源码分析。
简单说明一下:
各种 Encoder driver 和 CRCT driver 被 probe,然后通过 component_add() 注册进系统;
Rockchip DRM Master device 被 probe:
将各种 Encoder driver 和 CRCT driver 通过 component_match_add() 注册进 component match list;
component_master_add_with_match() 触发各种Encoder 和 CRCT component 的bind 操作,例如 vop_bind()、dw_hdmi_rockchip_bind() 等。
bind 的含义就是将 DRM 框架里的组件关联在一起,以 vop_bind() 为例:
-
VOP Driver 对应 CRCT driver, CRTC 负责连接 Planes 和 Encoder;
vop_create_crtc() -> drm_crtc_init_with_planes() 创建了 CRTC 对象,并和 Planes 关联在一起;
剩下的就是边边角角的工作,例如注册 framebuffer 以兼容 FBDEV,显示 logo等。
五、辅助调试的工具
1. sysfs
查看当前的显示状态,下面是只接了 HDMI 的情况:
-
$ cat /sys/kernel/debug/dri/ 0/summary
-
VOP [ff900000.vop]: ACTIVE
-
Connector: HDMI-A
-
overlay_mode[ 0] bus_format[ 100a] output_mode[f] color_space[ 0]
-
Display mode: 1920x1080p60
-
clk[ 148500] real_clk[ 148500] type[ 48] flag[ 5]
-
H: 1920 2008 2052 2200
-
V: 1080 1084 1089 1125
-
win0 -0: ACTIVE
-
format: XR24 little-endian ( 0x34325258) SDR[ 0] color_space[ 0]
-
csc: y2r[ 0] r2r[ 0] r2y[ 0] csc mode[ 0]
-
zpos: 0
-
src: pos[ 0x0] rect[ 1920x1080]
-
dst: pos[ 0x0] rect[ 1920x1080]
-
buf[ 0]: addr: 0x0000000000000000 pitch: 7680 offset: 0
-
win1 -0: DISABLED
-
win2 -0: DISABLED
-
win2 -1: DISABLED
-
win2 -2: DISABLED
-
win2 -3: DISABLED
-
win3 -0: DISABLED
-
win3 -1: DISABLED
-
win3 -2: DISABLED
-
win3 -3: DISABLED
-
post: sdr2hdr[ 0] hdr2sdr[ 0]
-
pre : sdr2hdr[ 0]
-
post CSC: r2y[ 0] y2r[ 0] CSC mode[ 1]
-
VOP [ff8f0000.vop]: DISABLED
查看某个具体的显示设备:
-
$ ls /sys/class/drm/
-
card0 card0-DP -1 card0-eDP -1 card0-HDMI-A -1 controlD64 renderD128 version
2. 调整 DRM log 等级
/sys/module/drm/parameters/debug
debug 里的每一个 bit 的含义:
Bit 0: enable CORE messages (drm core code)
Bit 1: enable DRIVER messages (drm controller code)
Bit 2: enable KMS messages (modesetting code)
Bit 3: enable PRIME messages (prime code)
Bit 4: enable ATOMIC messages (atomic code)
Bit 5: enable VBL messages (vblank code) (int)
3. libdrm/modetest
modetest 是由 libdrm 提供的测试程序,可以查询显示设备的支持状况,进行基本的显示测试,以及设置显示的模式。
-
$ git clone https: //gitlab.freedesktop.org/mesa/drm
-
$ apt-get install meson
-
$ meson builddir/
-
$ ninja -C builddir/ install
-
$ ./builddir/tests/modetest/modetest -h
-
usage: ./builddir/tests/modetest/modetest [-acDdefMPpsCvrw]
-
...
六、参考
Linux kernel Documentation
Rockchip RK3399 Datasheet V2.1-20200323.pdf
Rockchip_Introduction_DRM_Integration_Helper_CN.pdf
Rockchip DRM Display Driver Development Guide V1.0.pdf
Rockchip_Developer_Guide_DRM_Panel_Porting_CN.pdf
The DRM/KMS subsystem from a newbie’s point of view.pdf
思考技术,也思考人生
要学习技术,更要学习如何生活。
你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。
对 嵌入式系统 (Linux、RTOS、OpenWrt、Android) 和 开源软件 感兴趣,关注公众号:嵌入式Hacker。
觉得文章对你有价值,不妨点个 在看和赞。
-
转载:https://blog.csdn.net/wuweidonggmail/article/details/111659481