DRM 驱动程序开发(开篇)

DRM 驱动程序开发(开篇)前言在前面的 最简单的 DRM 应用程序 系列文章中 我们学习了如何使用 libdrm 接口编写 DRM 应用程序 从本篇开始 我们将进入一个全新的世界 一起来学习如何在 kernel 空间编写 DRM 驱动程序 Objects 在开始编写 DRM 驱动程序之前 我有必要对 DRM 内部的 Objects 进行一番介绍 因为这些 Objects 是 DRM 框架的核心 它们缺一不可 上图蓝色部

前言

在前面的《最简单的DRM应用程序》系列文章中,我们学习了如何使用 libdrm 接口编写 DRM 应用程序。从本篇开始,我们将进入一个全新的世界,一起来学习如何在 kernel 空间编写 DRM 驱动程序。

Objects

在开始编写 DRM 驱动程序之前,我有必要对 DRM 内部的 Objects 进行一番介绍。因为这些 Objects 是 DRM 框架的核心,它们缺一不可。

在这里插入图片描述

上图蓝色部分则是对物理硬件的抽象,黄色部分则是对软件的抽象。虚线以上的为 drm_mode_object,虚线以下为 drm_gem_object

之前曾在《DRM(Direct Rendering Manager)学习简介》中对这些 objects 做过简要介绍,作为本篇的重中之重,我觉得有必要再强调一下这些 objects 的概念:

object 说明
crtc RGB 信号发生源(TCON),显存切换控制器(Dislay Controller)
plane Display Controller 的数据源通道,每个 crtc 至少要有一个 plane
encoder RGB 信号转换器(DSI Contoller),同时也控制显示设备的休眠唤醒
connector 凡是能获取到显示参数的硬件设备,但通常和 encoder 绑定在一起
framebuffer 只用于描述显存信息(如 format、pitch、size 等),不负责显存的分配释放
property atomic 操作的基础,任何想要修改的参数都可以做成 property,供用户空间使用
gem 负责显存的分配、映射和释放

这些 objects 之间的关系:

在这里插入图片描述

通过上图可以看到,plane 是连接 framebuffer 和 crtc 的纽带,而 encoder 则是连接 crtc 和 connector 的纽带。与物理 buffer 直接打交道的是 gem 而不是 framebuffer。

需要注意的是,上图蓝色部分即使没有实际的硬件与之对应,在软件驱动中也需要实现这些 objects,否则 DRM 子系统无法正常运行。

drm_panel

drm_panel 不属于 objects 的范畴,它只是一堆回调函数的集合。但它的存在降低了 LCD 驱动与 encoder 驱动之间的耦合度。

在这里插入图片描述

为了解决该耦合的问题,DRM 子系统为开发人员提供了 drm_panel 结构体,该结构体封装了 connector & encoder 对 LCD 访问的常用接口。

在这里插入图片描述

于是,原来的 Encoder 驱动和 LCD 驱动之间的耦合,就转变成了上图中 Encoder 驱动与 drm_panel、drm_panel 与 LCD 驱动之间的“耦合”,从而实现了 Encoder 驱动与 LCD 驱动之间的解耦合。

小技巧:

为了方便驱动程序设计,通常都将 encoder 与 connector 放在同一个驱动中初始化,即 encoder 在哪,connector 就在哪。

如何抽象硬件

对于初学者来说,往往让他们迷惑的不是 DRM 中 objects 的概念,而是如何去建立这些 objects 与实际硬件的对应关系。因为并不是所有的 Display 硬件都能很好的对应上 plane/crtc/encoder/connector 这些 objects。下面我们就来一起学习,如何去抽象显示硬件到具体的 DRM object。

MIPI DSI 接口

下图为一个典型的 MIPI DSI 接口屏的硬件连接框图:

在这里插入图片描述

它在软件架构上与 DRM object 的对应关系如下图:

在这里插入图片描述

多余的细节不做介绍,这里只说明为何如此分配 drm object:

object 说明
crtc RGB timing的产生,以及显示数据的更新,都需要访问 Dislay Controller 硬件寄存器,因此放在 Display Controller 驱动中
plane 对 Overlay 硬件的抽象,同样需要访问 Display Controller 寄存器,因此也放在 Display Controller 驱动中
encoder 将 RGB 并行信号转换为 DSI 串行信号,需要配置 DSI 硬件寄存器,因此放在 DSI Controller 驱动中
connector 可以通过 drm_panel 来获取 LCD 的 mode 信息,但是 encoder 在哪,connector 就在哪,因此放在 DSI Controller 驱动中
drm_panel 用于获取 LCD mode 参数,并提供 LCD 休眠唤醒的回调接口,供 encoder 调用,因此放在 LCD 驱动中

驱动参考:https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c

MIPI DPI 接口

DPI 接口也就是我们常说的 RGB 并行接口,Video 数据通过 RGB 并行总线传输,控制命令(如初始化、休眠、唤醒等)则通过 SPI/I2C 总线传输,比如早期的 S3C2440 SoC 平台。下图为一个典型的 MIPI DPI 接口屏的硬件连接框图:

在这里插入图片描述

该硬件连接在软件架构上与 DRM object 的对应关系如下图:

在这里插入图片描述

多余的细节不做介绍,这里只说明为何如此分配 drm object:

object 说明
crtc RGB timing的产生,以及显示数据的更新,都需要访问 LCD Controller 硬件寄存器,因此放在 LCD Controller 驱动中
plane LCDC 没有 Overlay 硬件,它只有一个数据源通道,被抽象为 Primary Plane,同样需要访问 LCDC 硬件寄存器,因此放在 LCDC 驱动中
encoder 由于 DPI 接口本身不需要对 RGB 信号做任何转换,因此没有哪个硬件与之对应。但是 drm objects 又缺一不可,因此实现了一个虚拟的 encoder object。至于为什么要放在 LCDC 驱动中实现,纯粹只是为了省事而已,你也可以放在一个虚拟的平台驱动中去实现该 encoder object。
connector encoder 在哪,connector 就在哪,没什么好说的了
drm_panel 用于获取 LCD mode 参数,并提供 LCD 休眠唤醒的回调接口,供 encoder 调用,因此放在 LCD 驱动中

驱动参考:https://elixir.bootlin.com/linux/v5.0/source/drivers/gpu/drm/panel/panel-sitronix-st7789v.c

MIPI DBI 接口

DBI 接口也就是我们平时常说的 MCU 或 SPI 接口屏,这类屏的 VIDEO 数据和控制命令都是通过同一总线接口(I80、SPI接口)进行传输,而且这类屏幕必须内置 GRAM 显存,否则屏幕无法维持正常显示。

下图为一个典型的 DBI 接口屏的硬件连接框图:

在这里插入图片描述

该硬件连接在软件架构上与 DRM object 的对应关系如下:

在这里插入图片描述

上图参考 kernel4.19 tinydrm 软件架构。

object 说明
crtc 这类硬件本身不需要任何 RGB timing 信号,因此也没有实际的硬件与之对应。但是 drm objects 缺一不可,需要实现一个虚拟的 crtc object。由于更新图像数据的动作需要通过 SPI 总线发送命令才能完成,因此放在了 LCD 驱动中
plane 没有实际的硬件与之对应,但 crtc 初始化时需要一个 plane object 作为参数传递,因此和 crtc 放在一起
encoder 没有实际的硬件与之对应,使用虚拟的 encoder object。因为这类硬件并不是将 RGB 信号转换为 SPI 信号,而是根本就没有 RGB 信号源,也就无从谈起 encoder 设备。但是为了通知 LCD 休眠唤醒,需要调用 LCD 驱动的相应接口,因此放在 LCD 驱动中
connector 由于没有了 drm_panel,需要调用 LCD 接口来获取 mode 参数,因此放在 LCD 驱动中

驱动参考:https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/tinydrm/ili9341.c

总结

  • 这 7 个 objects 缺一不可
  • framebuffer 只是负责描述显存信息,gem 则负责显存的分配/释放等操作
  • encoder 在哪里,connector 就在哪里

在下一篇文章中,我们将开始真正动手编写一个《最简单的 DRM 驱动程序》,尽情期待!

往期回顾:

DRM (Direct Rendering Manager) 学习简介

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176266.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午10:20
下一篇 2026年3月26日 下午10:21


相关推荐

  • 认证鉴权

    认证鉴权

    2026年3月12日
    3
  • 轻松学会python的turtle模块,画一箭穿心、小人儿发射爱心、520表白完整代码,海龟作图小创意「建议收藏」

    轻松学会python的turtle模块,画一箭穿心、小人儿发射爱心、520表白完整代码,海龟作图小创意「建议收藏」当我们学了turtle后(如果不懂turtle模块的话,文章末尾会详细介绍的),就想尝试为自己心里喜欢的人画一颗一颗爱心,想用代码逗自己的小猪猪女孩开心,表达自己的爱意,那么福利来了,动动小手指,复制粘贴即可,不过有些地方需要适当修改,快给自己心爱的女孩看看吧importturtleimporttime#实现清屏defclear_screen():

    2022年6月28日
    64
  • pycharm使用pip安装模块_pycharm安装pip不是内部指令

    pycharm使用pip安装模块_pycharm安装pip不是内部指令pycharm使用pip更换安装源在Pycharm底部的Terminal输入//AnhighlightedblockPSD:\Users>pipconfigsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simple–trusted-hostpypi.tuna.tsinghua.edu.cnWritingtoC:\Users\AppData\Roaming\pip\pip.ini#下面这行代码是查

    2022年8月29日
    5
  • Python 日志输出

    Python 日志输出Python 日志输出

    2022年4月24日
    48
  • MSDP配置(anycast RP)

    MSDP配置(anycast RP)实验拓扑:案例配置需求:1、 设备之间互联的IP如图所示;2、 R1和R2设备互联使用12.1.1.X/24,X表示设备编号,如R1使用12.1.1.1/24,R2使用12.1.1.2/24,其它设备互联同上;3、 AS100内IGP协议运行OSPF协议,AS200内IGP协议运行EIGRP协议;4、 R3和R4配置运行BGP协议,建立EBGP邻居关系;5、 配置组播稀疏模式,其中…

    2022年5月18日
    75
  • C语言typedef的用法详解

    C语言typedef的用法详解C 语言允许为一个数据类型起一个新的别名 就像给人起 绰号 一样 起别名的目的不是为了提高程序运行效率 而是为了编码方便 例如有一个结构体的名字是 stu 要想定义一个结构体变量就得这样写 structstustu struct 看起来就是多余的 但不写又会报错 如果为 structstu 起了一个别名 STU 书写起来就简单了 STUstu1 这种写法更加简练 意义也非常明

    2026年3月19日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号