开启辅助访问
 找回密码
 立即注册

RK3399 探索之旅 / Display子系统 / 从 modetest 到 DRM driver

zsldgjk 回答数0 浏览数657
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 id
  • 64: 某个 VOP 的 crtc id
  • 1920x1080:显示 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 id
  • 83: 另外一台 VOP 的 crtc id
  • 1920x1080:显示 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 CRCT Driver(例如 Rockchip VOP driver) 里都会定义一台 struct drm_crtc_funcs 结构体,其中的 .set_config 都指向 drm_atomic_helper_set_config(),接下来就是 DRM core 开始工作了。
五、相关参考


  • 《RK3399 探索之旅 / Display 子系统 / 基础概念》
  • 小龙兄的博客: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
觉得文章对你有价值,不妨点个 在看和赞
使用道具 举报
| 来自江苏
当贝投影