一.显示系统概述
linux内核中包含两类图形显示设备驱动框架:
- FB设备:Framebuffer图形显示框架;
- DRM:直接渲染管理器(- Direct Rendering Manager),是- linux目前主流的图形显示框架;
在实际场景中,具体选择哪一种图形设备驱动框架取决于我们自己的业务需求。
Frambebuffer驱动
 
Frambebuffer驱动具有以下特征:
直接控制显卡的帧缓冲区,提供基本的显卡输出功能;
使用一些内核数据结构和API来管理图形界面,并提供一组接口与用户空间的应用程序进行通信;
相对简单,适合于嵌入式系统或者不需要高性能图形的应用场景。
DRM驱动
 
DRM驱动具有以下特征:
相比FB(Framebuffer)架构,DRM更能适应当前日益更新的显示硬件;
提供一种分离的图形驱动架构,将硬件驱动程序、内核模块和用户空间驱动程序进行分离;
支持多个应用程序同时访问显卡,并提供了更丰富的图形功能,例如硬件加速和3D加速;
提供了一些内核接口,可以让用户空间应用程序与驱动程序进行交互;
支持多显示器(Display)和多GPU的配置;
总之,一句话,DRM是Linux目前主流的图形显示框架,相比FB架构,DRM更能适应当前日益更新的显示硬。尽管FB退出历史舞台,但是并未将其遗弃,而是集合到DRM中,供部分嵌入式设备使用。
二.DRM框架
 
DRM子系统的软件架构

DRM框架从上到下依次为应用程序、libdrm、DRM driver、HW;
(1) 应用程序:上图中并没有画出;应用程序可以直接操纵DRM的ioctl进行显示相关操作,后来封装成了libdrm库,让用户可以更加方便的进行显示控制;
(2) libdrm:lbdrm是DRM框架提供的位于用户空间操作DRM的库,提供了DRM驱动的用户空间接口;对底层接口进行封装,向上层应用程序提供通用的API接口,本质上是对各种ioctl接口进行封装;
(3) DRM core:DRM核心层,由GEM和KMS组成;
- KMS:- Kernel Mode Setting,所谓内核显示模式设置,其实说白了就两件事:更新画面和设置显示参数;- 更新画面:显示buffer的切换,多图层的合成方式,以及每个图层的显示位置;
- 设置显示参数:包括分辨率、刷新率、电源状态(休眠唤醒)等;
 
- 更新画面:显示
- GEM:- Graphic Execution Manager(图形执行管理器),它提供了一种抽象的显存管理方式,使用户空间应用程序可以更方便地管理显存,而不需要了解底层硬件的细节;- 实际上,在DRM中包含两个内存管理器,TTM(Translation Table Manager)和GEM(Graphic Execution Manager),TTM是第一个开发的DRM内存管理器,关于TTM我们就不做过多的介绍了,知道有这么一个东西就好了。
 
- 实际上,在DRM中包含两个内存管理器,
(4) HW:硬件设备;
KMS
 
KMS主要负责显示相关功能,在DRM中将其进行抽象,包括:CRTC、ENCODER、CONNECTOR、PLANE、Framebuffer、VBLANK、property;它们之间的关系如下图所示:

以HDMI接口为例说明,Soc内部一般包含一个Display模块,通过总线连接到HDMI接口上;
- Display模块对应- CRTC;
- HDMI接口对应- Connector;
- Framebuffer对应的是显存部分;
- Plane是对- Framebuffer进行描述的部分;
- Encoder是将像素转化为- HDMI接口所需要的信号,一般- Encoder和- Connector放到一块初始化。
GEM
 
GEM主要负责显示buffer的分配和释放,在DRM中将其进行抽象,包括:DUMP、PRIME、fence;
三.元素介绍
CRTC:
从Framebuffer中读取待显示的图像,并按照响应的格式输出给encoder,其主要承担的作用为
 (1)配置适合显示的显示模式、分辨率、刷新率等参数,并输出相应的时序;
 (2)扫描Framebuffer发送到一个或多个显示器;
 (3)更新Framebuffer;
 概括下就是,对显示器进行扫描,产生时序信号的模块、负责帧切换、电源控制、色彩调整等等。
Encoder:
编码器。它的作用就是将内存的pixel像素编码(转换)为显示器所需要的信号。
 简单理解就是,如果需要将画面显示到不同的设备(Display Device)上,需要将画面转化为不同的电信号,例如DVID、VGA、YPbPr、CVBS、MIPI、eDP 等。Encoder和CRTC之间的交互就是我们所说的Mode Setting,其中包含了前面提到的色彩模式、还有时序(Timing)等
Connector:
连接器。它常常对应于物理连接器 (例如VGA,DVI, FPD-Link, HDMI, DisplayPort, S-Video等) ,它不是指物理线。
 在DRM中,Connector 是一个抽象的数据结构,代表连接的显示设备,从Connector中可以得到当前物理连接的输出设备相关的信息 ;例如连接状态,EDID数据,DPMS状态、支持的视频模式等。
Plane:
图层,实际输出的图像是多个图层叠加而成的,比如主图层、光标图层。其中有些图层由硬件加速模块生成,每个CRTC至少一个plane;plane一共有三种,分别是:DRM_PLANE_TYPE_PRIMARY、DRM_PLANE_TYPE_OVERLAY、DRM_PLANE_TYPE_CURSOR。这是配置plane的三个枚举,标注主图层、覆盖图层、光标图层;
Framebuffer:
Framebuffer,用于存储单个图层(Plane)要实现的内容
 它是一块内存区域,可以理解为一块画布,驱动程序和应用都能访问它。绘画前需要将它格式化,设定绘制的色彩模式(例如RGB888,YUV等)和画布的大小(分辨率)。
Vblank:
软件和硬件的同步机制,RGB时序中的垂直消影区,软件通常使用硬件VSYNC来实现。
四.目录结构
linux内核将DRM驱动相关的代码都放在drivers/gpu/drm目录下,这下面的文件还是比较多的,我们大概了解一下即可;
linux-6.3# ls drivers/gpu/drm/ -I "*.o"
amd                         drm_fbdev_generic.c             drm_print.c                logicvc
arm                         drm_fb_dma_helper.c             drm_privacy_screen.c       Makefile
armada                      drm_fb_helper.c                 drm_privacy_screen_x86.c   mcde
aspeed                      drm_file.c                      drm_probe_helper.c         mediatek
ast                         drm_flip_work.c                 drm_property.c             meson
atmel-hlcdc                 drm_format_helper.c             drm_rect.c                 mgag200
bridge                      drm_fourcc.c                    drm_scatter.c              modules.order
built-in.a                  drm_framebuffer.c               drm_self_refresh_helper.c  msm
display                     drm_gem_atomic_helper.c         drm_shmem_helper.ko        mxsfb
drm_agpsupport.c            drm_gem.c                       drm_shmem_helper.mod       nouveau
drm_aperture.c              drm_gem_dma_helper.c            drm_shmem_helper.mod.c     omapdrm
drm_atomic.c                drm_gem_framebuffer_helper.c    drm_simple_kms_helper.c    panel
drm_atomic_helper.c         drm_gem_shmem_helper.c          drm_syncobj.c              panfrost
drm_atomic_state_helper.c   drm_gem_ttm_helper.c            drm_sysfs.c                pl111
drm_atomic_uapi.c           drm_gem_vram_helper.c           drm_trace.h                qxl
drm_auth.c                  drm_hashtab.c                   drm_trace_points.c         radeon
drm_blend.c                 drm_internal.h                  drm_ttm_helper.ko          rcar-du
drm_bridge.c                drm_ioc32.c                     drm_ttm_helper.mod         rockchip
drm_bridge_connector.c      drm_ioctl.c                     drm_ttm_helper.mod.c       scheduler
drm_buddy.c                 drm_irq.c                       drm_vblank.c               shmobile
drm_bufs.c                  drm_kms_helper_common.c         drm_vblank_work.c          solomon
drm_cache.c                 drm_lease.c                     drm_vma_manager.c          sprd
drm_client.c                drm_legacy.h                    drm_vm.c                   sti
drm_client_modeset.c        drm_legacy_misc.c               drm_vram_helper.ko         stm
drm_color_mgmt.c            drm_lock.c                      drm_vram_helper.mod        sun4i
drm_connector.c             drm_managed.c                   drm_vram_helper.mod.c      tegra
drm_context.c               drm_memory.c                    drm_writeback.c            tests
drm_crtc.c                  drm_mipi_dbi.c                  etnaviv                    tidss
drm_crtc_helper.c           drm_mipi_dsi.c                  exynos                     tilcdc
drm_crtc_helper_internal.h  drm_mm.c                        fsl-dcu                    tiny
drm_crtc_internal.h         drm_mode_config.c               gma500                     ttm
drm_damage_helper.c         drm_mode_object.c               gud                        tve200
drm_debugfs.c               drm_modes.c                     hisilicon                  udl
drm_debugfs_crc.c           drm_modeset_helper.c            hyperv                     v3d
drm_displayid.c             drm_modeset_lock.c              i2c                        vboxvideo
drm_dma.c                   drm_of.c                        i915                       vc4
drm_drv.c                   drm_panel.c                     imx                        vgem
drm_dumb_buffers.c          drm_panel_orientation_quirks.c  ingenic                    virtio
drm_edid.c                  drm_pci.c                       Kconfig                    vkms
drm_edid_load.c             drm_plane.c                     kmb                        vmwgfx
drm_encoder.c               drm_plane_helper.c              lib                        xen
drm_encoder_slave.c         drm_prime.c                     lima                       xlnx其中:
-  drm_drv.c:DRM core核心实现;
-  drm_gem.c:提供了GEM相关的API;
其中rockchip为Rockchip官方的实现代码:
linux-6.3# ls drivers/gpu/drm/rockchip/ -I "*.o"
analogix_dp-rockchip.c  inno_hdmi.c         rockchip_drm_drv.h   rockchip_drm_vop.h
built-in.a              inno_hdmi.h         rockchip_drm_fb.c    rockchip_lvds.c
cdn-dp-core.c           Kconfig             rockchip_drm_fb.h    rockchip_lvds.h
cdn-dp-core.h           Makefile            rockchip_drm_gem.c   rockchip_rgb.c
cdn-dp-reg.c            modules.order       rockchip_drm_gem.h   rockchip_rgb.h
cdn-dp-reg.h            rk3066_hdmi.c       rockchip_drm_vop2.c  rockchip_vop2_reg.c
dw_hdmi-rockchip.c      rk3066_hdmi.h       rockchip_drm_vop2.h  rockchip_vop_reg.c
dw-mipi-dsi-rockchip.c  rockchip_drm_drv.c  rockchip_drm_vop.c   rockchip_vop_reg.h