DRM(7) -- Connector

DRM connector 是对显示接收器 (display sink) 的抽象,包括固定的 panels, 或者其他任何可以显示像素的东西。 通过 drm_connector_init() 和 drm_connector_register() 初始化和注册。 connector 使用前必须 attach 到 encoder 上,对于 encoder 和 connector 1:1 的情况,在初始化流程中调用 drm_connector_attach_encoder(). Data Structure struct drm_connector { struct drm_device *dev; struct device *kdev; struct device_attribute *attr; struct fwnode_handle *fwnode; struct list_head head; struct list_head global_connector_list_entry; struct drm_mode_object base; char *name; struct mutex mutex; unsigned index; int connector_type; int connector_type_id; bool interlace_allowed; bool doublescan_allowed; bool stereo_allowed; bool ycbcr_420_allowed; enum drm_connector_registration_state registration_state; struct list_head modes; enum drm_connector_status status; struct list_head probed_modes; struct drm_display_info display_info; const struct drm_connector_funcs *funcs; struct drm_property_blob *edid_blob_ptr; struct drm_object_properties properties; uint8_t polled; const struct drm_connector_helper_funcs *helper_private; struct drm_cmdline_mode cmdline_mode; enum drm_connector_force force; u64 epoch_counter; u32 possible_encoders; struct drm_encoder *encoder; struct i2c_adapter *ddc; struct dentry *debugfs_entry; struct drm_connector_state *state; }; connector_type: DRM_MODE_CONNECTOR_XXX。...

2024-09-18 · 4 min

DRM(4) -- CRTC

Overview CRTC 代表整个 display pipeline。它接收来自 drm_plane 的像素数据并将它们混合在一起。drm_display_mode 也附加在 CRTC 上,用于指定显示时序。在输出端,数据被送入一个或多个 drm_encoder,然后每个 encoder 都连接到一个 drm_connector 上。 crtc 使用drm_crtc_init_with_planes() 来初始化。 数据结构 drm_crtc struct drm_crtc { struct drm_device *dev; struct device_node *port; struct list_head head; char *name; struct drm_modeset_lock mutex; struct drm_mode_object base; unsigned index; const struct drm_crtc_funcs *funcs; const struct drm_crtc_helper_funcs *helper_private; struct drm_object_properties properties; struct drm_property *scaling_filter_property; struct drm_crtc_state *state; struct list_head commit_list; spinlock_t commit_lock; struct dentry *debugfs_entry; struct drm_crtc_crc crc; unsigned int fence_context; spinlock_t fence_lock; unsigned long fence_seqno; char timeline_name[32]; struct drm_self_refresh_data *self_refresh_data; }; drm_crtc_state struct drm_crtc_state { struct drm_crtc *crtc; bool enable; bool active; bool planes_changed : 1; bool mode_changed : 1; bool active_changed : 1; bool connectors_changed : 1; bool zpos_changed : 1; bool color_mgmt_changed : 1; bool no_vblank : 1; u32 plane_mask; u32 connector_mask; u32 encoder_mask; struct drm_display_mode adjusted_mode; struct drm_display_mode mode; struct drm_property_blob *mode_blob; struct drm_property_blob *degamma_lut; struct drm_property_blob *ctm; struct drm_property_blob *gamma_lut; u32 target_vblank; bool async_flip; bool vrr_enabled; bool self_refresh_active; enum drm_scaling_filter scaling_filter; struct drm_pending_vblank_event *event; struct drm_crtc_commit *commit; struct drm_atomic_state *state; }; enable: userspace set CRTC MODE_ID property, 进入 drm_atomic_set_mode_prop_for_crtc() 函数中设置 crtc 的 enable 状态。...

2024-09-04 · 4 min

DRM(9) -- Object and Property

Modeset Base Object Abstraction 所有 KMS objects 的 base structure 是 struct drm_mode_object, 用来追踪 property. property 可以通过 drm_object_attach_property() attach 到不同的 object 上。 Object 每个 drm mode 包括 drm_crtc, drm_connector, drm_framebuffer 等结构体中都会有一个 drm_mode_object 数据结构,其中保存了该 crtc/connector/fb/plane 的 id, 用于 id tracking. 还有对应的 property 属性等。 drm_mode_object 结构体: struct drm_mode_object { uint32_t id; uint32_t type; struct drm_object_properties *properties; struct kref refcount; void (*free_cb)(struct kref *kref); } id: 用户空间操作的 id. type: DRM_MODE_OBJECT_XXX, 包括 DRM_MODE_OBJECT_CRTC/CONNECTOR/ENCODER/MODE/PROPERTY/FB/BLOB/PLANE/ANY Userspace 只能对 CONNECTOR, CRTC, PLANE 三种 type 的 object property 进行设置 properties: drm object 用来追踪 property 的结构体。...

2024-09-02 · 4 min

DRM(3) -- Atomic commit

Atomic Mode Setting 在 DRM 子系统中,atomic mode setting 是指一种用于显示配置更新的机制,它允许将多个显示参数的变更作为一个原子性的操作一次性提交和应用。 整个更新作为一个单元被处理,不会出现部分应用的情况,所有显示参数的变更在同一个垂直消隐期间同步生效。 drm_atomic_state - 包含整个显示状态的快照 drm_crtc_state, drm_plane_state, drm_connector_state - 各组件的状态对象 crtc, plane, connector object 都包含一个 state,drm_plane_state, drm_crtc_state, drm_connector_state,这些 state 是在 atomic 过程中用户可见并且设置的。 在 driver 内部,如果需要保存一些内部状态,可以 subclass 这些 state,或者一个整体的 drm_private_state. Handling Driver Private State 通常 DRM objects (connector, crtc, plane) 不能与硬件完全的匹配映射。 比如在 planes, crtc 等之间一些共享的资源,shared clock, scaler units, bandwidth, fifo limits. 这时候我们需要创建一个仅内部可见的 private state. struct drm_private_state { struct drm_atomic_state *state; struct drm_private_obj *obj; }; state: backpointer,指向 atomic state...

2024-08-28 · 4 min

DRM(10) -- VBlank

Overview 一篇关于垂直同步 V-Sync 解释的文章:https://daily.elepover.com/2021/03/27/vsync/index.html 当 GPU 渲染的速度 > 显示器刷新的速度时,GPU 在显示器还来不及完成渲染完一帧时,就切换了 framebuffer,会导致出现撕裂现象。 帧率大于显示器刷新率时,启用垂直同步。 帧率小于显示器刷新率时,禁用垂直同步。 为了支持 vblank,底层 drvier 需要调用 drm_vblank_init() 初始化,另外需要实现 drm_crtc_funcs.enable_vblank 和 drm_crtc_funcs.disable_vblank 两个回调函数,并且在 vblank 中断中调用 drm_crtc_handle_vblank()。 数据结构 每个 crtc 对应一个 struct drm_vblank_crtc 结构体。 struct drm_vblank_crtc { struct drm_device *dev; wait_queue_head_t queue; struct timer_list disable_timer; seqlock_t seqlock; atomic64_t count; ktime_t time; atomic_t refcount; u32 last; u32 max_vblank_count; unsigned int inmodeset; unsigned int pipe; int framedur_ns; int linedur_ns; struct drm_display_mode hwmode; bool enabled; struct kthread_worker *worker; struct list_head pending_work; wait_queue_head_t work_wait_queue; }; refcount: vblank interrupt user/waiter 数量。...

2024-08-28 · 3 min

DRM(2) -- KMS Core

Kernel Mode Setting (KMS) driver 通过 drmm_mode_config_init() 来初始化 mode setting. Overview KMS pipeline: 一个 crtc 可以有多个 encoder, 一个 encoder 对应一个 connector, 并且中间可以接任意个 bridge. 通常对于有 bridge 的 driver, encoder 层不需要任何代码。 Data Structure and api struct drm_mode_config_funcs mode setting functions, 该结构体需要在底层 driver 中初始化。 struct drm_mode_config_funcs { struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd); const struct drm_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd); enum drm_mode_status (*mode_valid)(struct drm_device *dev, const struct drm_display_mode *mode); int (*atomic_check)(struct drm_device *dev, struct drm_atomic_state *state); int (*atomic_commit)(struct drm_device *dev,struct drm_atomic_state *state, bool nonblock); }; fb_create: 创建 framebuffer 的回调函数,在 userspace 调用 drmModeAddFB2() 之后会调用到。....

2024-08-28 · 3 min

DRM(6) -- Plane

在扫描输出过程中,一个平面(plane)代表一个图像源,CRTC 可以对平面进行混合(blend)或叠加(overlaid)显示。plane 从 drm_framebuffer 获取输入数据。平面本身定义了图像的裁剪(cropping)和缩放(scaling)方式,以及它在 display pipeline 可见区域中的位置。平面还可以具有额外的属性来指定平面像素的定位和混合方式,比如旋转(rotation)或 Z 轴位置(Z-position)。所有这些属性都存储在 drm_plane_state 中。 plane 由 struct drm_plane 表示,使用drm_universal_plane_init() 初始化。 每个 plane 都有一个类型,参考 enum drm_plane_type。 每个 CRTC 都必须要有一个 primary plane。 Data structure and api struct drm_plane { struct drm_device *dev; struct list_head head; char *name; struct drm_modeset_lock mutex; struct drm_mode_object base; uint32_t possible_crtcs; uint32_t *format_types; unsigned int format_count; uint64_t *modifiers; unsigned int modifier_count; const struct drm_plane_funcs *funcs; struct drm_object_properties properties; enum drm_plane_type type; unsigned index; const struct drm_plane_helper_funcs *helper_private; struct drm_plane_state *state; struct drm_property *alpha_property; struct drm_property *zpos_property; struct drm_property *rotation_property; struct drm_property *blend_mode_property; struct drm_property *color_encoding_property; struct drm_property *color_range_property; struct drm_property *scaling_filter_property; struct drm_property *hotspot_x_property; struct drm_property *hotspot_y_property; }; possible_crtcs: 该 plane 支持的 crtc 类型,在 plane 初始化时传入。...

2024-08-28 · 4 min

DRM(5) -- FrameBuffer

Framebuffer 帧缓冲区是抽象的内存对象,提供了扫描到 CRTC 的像素源。应用程序通过 IOCTLDRM_IOCTL_MODE_ADDFB(2)来创建 framebuffer,会返回一个不透明句柄,该句柄可以传递给 KMS CRTC、来控制 plane configuration 和 page flip 功能。 framebuffer 依赖底层的内存管理器来分配内存。创建 framebuffer 时,app 需要通过struct drm_mode_fb_cmd2传入一个 memory handle。 Data structures and apis struct drm_framebuffer { struct drm_device *dev; struct list_head head; struct drm_mode_object base; const struct drm_format_info *format; const struct drm_framebuffer_funcs *funcs; unsigned int pitches[DRM_FORMAT_MAX_PLANES]; unsigned int offsets[DRM_FORMAT_MAX_PLANES]; uint64_t modifier; unsigned int width; unsigned int height; int flags; struct list_head filp_head; struct drm_gem_object *obj[DRM_FORMAT_MAX_PLANES]; }; head: fb 链表节点。...

2024-08-28 · 4 min

BT.656 协议介绍

预备知识 场的概念 在视频传输协议中,“场”(field)是指构成一帧完整图像的两个半幅图像之一。在传统的隔行扫描视频系统中,一帧完整的图像由两个场组成:上场(top field)和下场(bottom field)。这种扫描方式主要用于模拟电视信号中,以减少带宽需求并提高图像质量。 场的基本概念: 隔行扫描:在隔行扫描中,屏幕上的像素不是一次性全部刷新,而是分成两个阶段来完成。首先刷新所有偶数行(上场),然后刷新所有奇数行(下场),这样就完成了一帧图像的显示。 上场与下场:上场包含所有偶数行,下场包含所有奇数行。这两个场结合在一起组成一帧完整的图像。 帧与场: 在隔行扫描中,每两场构成一帧。帧是完整的图像,而场则是帧的一半。因此,在模拟电视系统中,每秒显示的场数通常是帧数的两倍。 隔行扫描与逐行扫描的区别: 隔行扫描:每一帧图像分成两个场显示,每个场包含一半的扫描线。这种方式减少了带宽需求,但也可能导致运动图像出现闪烁或交错现象(interlacing effect)。 逐行扫描:每一帧图像的所有扫描线一次性显示完毕。这种方式可以提供更平滑的图像,但需要更大的带宽。 应用场景: 模拟电视系统:在 PAL 和 NTSC 等模拟电视标准中,使用隔行扫描技术来传输视频信号。例如,NTSC 系统的帧率为每秒 30 帧,但实际上是以每秒 60 场的速度传输。 PAL,NTSC,SECAM 三者都是模拟电视信号标准。 NTSC: 全称为 National Television Standards Committee。视频格式为一张 NTSC 的图片包含 525 个交错行(interlaced lines), 每秒 29.97 帧。 PAL: 全称为 Phase Alternate Line。视频格式为一张 PAL 图片 625 个交错行,每秒 25 帧。 SECAM: 全称为 Sequential Color and Memory。视频格式和 PAL 一样,一张 SECAM 图片 625 个交错行,每秒 25 帧。但是 SECAM 处理颜色信息的方式和 PAL 不同。...

2024-08-22 · 2 min

DRM -- Graphic Introduction

Reference https://docs.kernel.org/gpu/index.html introduction 中提供了一些关于 DRM 的讲座和 slides 材料。 https://bootlin.com/doc/training/graphics/graphics-slides.pdf Basic Theory and Concepts About Graphics YUV 数据格式 采样 YUV 格式,由一个 Y 的亮度分量(Luma)和 U(蓝色投影 Cb)和 V(红色投影 Cr)的色度分量(Chroma)表示。 4:4:4 表示不降低色度(UV)通道的采样率。每个 Y 分量对应一组 UV 分量。 4:2:2 表示 2:1 水平下采样,没有垂直下采样。每两个 Y 分量共享一组 UV 分量。 4:2:0 表示 2:1 水平下采样,同时 2:1 垂直下采样。每四个 Y 分量共享一组 UV 分量。 4:1:1 表示 4:1 水平下采样,没有垂直下采样。每四个 Y 分量共享一组 UV 分量。 BT.601 中规定的 YUV 和 RGB 的转换公式: \(R=Y+1.140*V-0.7\) \(G=Y-0.343*U-0.711*V+0.526\) \(B=Y+1.765*U-0.883\) \(Y=0.299*R+0.587*G+0.114*B\) \(U=-0.169*R-0.331*G+0.500*B\) \(V=0.500*R-0.439*G-0.081\*B\)...

2024-08-20 · 1 min