modetest 是由 libdrm 提供的测试程序,可以查询显示设备的特性,进行基本的显示测试,以及设置显示的模式。
我们可以借助该工具来学习 Linux DRM 应用编程,另外为了深入分析 Rockchip DRM driver,有必要先了解一下这个工具的使用方法和内部实现。
本文目录:
-
一、准备工作
-
-
二、modetest 使用示例
-
1. 查看帮助信息
-
2. 查看组件的信息
-
3. 在 HDMI 上显示
-
4. 在 eDP 上显示
-
-
三、编写最简单的 DRM 应用
-
-
四、DRM 应用如何呼叫到 Rockchip DRM driver?
-
-
五、相关参考
一、准备工作
在 NanoPC T4 + Linux-4.4 上:
接好 eDP 屏以及 HDMI 显示器;
退出所有占用 /dev/dri/card0 的程序;
编译 modetest
-
$ git clone https:
//gitlab.freedesktop.org/mesa/drm
-
$ apt-get install meson
-
$ meson builddir/
-
$ ninja -C builddir/ install
二、modetest 使用示例
1. 查看帮助信息
-
$ modetest -h
-
usage: modetest [-acDdefMPpsCvrw]
-
-
Query options:
-
-
-c list connectors
-
-e list encoders
-
-f list framebuffers
-
-p list CRTCs and planes (pipes)
-
-
Test options:
-
...
-
Generic options:
-
-
-d drop master after mode set
-
-M module use the given driver
-
-D device use the given device
-
-
Default is to dump all info.
2. 查看组件的信息
-
$ modetest -M rockchip
-
Encoders:
-
id crtc
type possible crtcs possible clones
-
76
54 TMDS
0x00000001
0x00000000
-
78
0 TMDS
0x00000003
0x00000000
-
80
65 TMDS
0x00000002
0x00000000
-
-
Connectors:
-
...
参数说明:
-M
:用于指定访问 rockchip DRM driver
关键内容:
Encoders / Connectors / CRTCs / Planes 的 id,modetest 通过 id 来用于引用这些组件。
Connectors 的 modes/props:
-
prop: 任何你想设置的参数,都可以做成 property,是 DRM 驱动中最灵活、最方便的 Mode setting 机制;
modes: 显示模式,mode 里包含分辨率/刷新率等显示相关的信息;
CRTCs 的 props;
Planes 的 formats/props;
各组件的 id:
-
$ modetest -M rockchip | cut -f1 | grep -E ^[
0
-9A-Z]\|id
-
-
Encoders:
-
id
-
90, edp encoder
-
92, hdmi encoder
-
100, dp encoder
-
Connectors:
-
id
-
91, edp connector
-
93, hdmi connector
-
101, dp connector
-
CRTCs:
-
id
-
64, vop crtc
-
83, vop crtc
-
Planes:
-
id
-
58
-
61
-
65
-
68
-
80
-
84
-
Frame buffers:
-
id
3. 在 HDMI 上显示
-
$ modetest -M rockchip -s
93@
64:
1920x1080
-
$ modetest -M rockchip -s
93@
64:#
1
// 相同的效果
参数说明:
-s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>]
:用于在指定的 pipeline 上以某个 mode 显示某个 pattern 的画面。93
:HDMI connector id64
:某个 VOP 的 crtc id1920x1080
:显示 mode;
HDMI connector 下其他可选的 mode:
-
#
0
1920x1080
60.00
-
#
1
1920x1080
59.94
-
#
2
1920x1080i
30.00
-
#
3
1920x1080i
29.97
-
...
-
#
24
640x480
60.00
-
#
25
640x480
59.94
-
#
26
720x400
70.08
显示效果:
4. 在 eDP 上显示
$ modetest -M rockchip -s 91@83:1920x1080
参数说明:
91
:eDP connector id83
:另外一个 VOP 的 crtc id1920x1080
:显示 mode;
显示效果:
三、编写最简单的 DRM 应用
主程序:
-
int main(
int argc, char **argv)
-
{
-
int fd;
-
drmModeConnector *conn;
-
drmModeRes *res;
-
uint32_t conn_id;
-
uint32_t crtc_id;
-
-
// 1. 打开设备
-
fd = open(
"/dev/dri/card0", O_RDWR | O_CLOEXEC);
-
-
// 2. 获得 crtc 和 connector 的 id
-
res = drmModeGetResources(fd);
-
crtc_id = res->crtcs[
0];
-
conn_id = res->connectors[
0];
-
-
// 3. 获得 connector
-
conn = drmModeGetConnector(fd, conn_id);
-
buf.width = conn->modes[
0].hdisplay;
-
buf.height = conn->modes[
0].vdisplay;
-
-
// 4. 创建 framebuffer
-
modeset_create_fb(fd, &buf);
-
-
// 5. Sets a CRTC configuration,这之后就会开始在 crtc0 + connector0 pipeline 上进行以 mode0 输出显示
-
drmModeSetCrtc(fd, crtc_id, buf.fb_id,
0,
0, &conn_id,
1, &conn->modes[
0]);
-
-
getchar();
-
-
// 6. cleanup
-
...
-
-
return
0;
-
}
modeset_create_fb():
该函数用于分配 framebuffer,目前不需要太关心,大致就是 3 个步骤:
Allocating memory;
Preparing a mapping;
Mapping memory;
运行效果:
程序运行后,eDP 屏显示全屏白色,等待用户输入按键;当用户按下任意按键后,程序退出,显示黑屏。
四、DRM 应用如何呼叫到 Rockchip DRM driver?
drmModeSetCrtc() 到 CRTC driver:
每一个 DRM CRTC Driver(例如 Rockchip VOP driver) 里都会定义一个 struct drm_crtc_funcs 结构体,其中的 .set_config 都指向 drm_atomic_helper_set_config(),接下来就是 DRM core 开始工作了。
五、相关参考
小龙兄的博客:https://blog.csdn.net/hexiaolong2009/article/details/83721242
nvidia 的文档:https://docs.nvidia.com/drive/nvvib_docs
Linux man 手册:man 7 drm
思考技术,也思考人生
要学习技术,更要学习如何生活。
你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。
对 嵌入式系统 (Linux、RTOS、OpenWrt、Android) 和 开源软件 感兴趣,关注公众号:嵌入式Hacker。
觉得文章对你有价值,不妨点个 在看和赞。
转载:https://blog.csdn.net/wuweidonggmail/article/details/112057675