• Rockchip RK3399 - DRM crtc基础知识


    一、LCD硬件原理

    1.1 CRT介绍

    CRT是阴极射线管(Cathode Ray Tube)的缩写,它是一种使用电子束在荧光屏上创建图像的显示设备。CRT显示器在过去很长一段时间内是主流的显示技术,现已被液晶显示屏或其他新兴技术所替代。

    CRT显示器中,扫描电子束从左到右、从上到下移动,照亮屏幕上的荧光点,从而创建图像。电子束每秒多次扫描整个屏幕,产生闪烁效果,需要与正在显示的内容同步。

    随着LCDLEDOLED等新型显示技术的出现,底层原理已经发生了变化。这些显示器不再使用扫描电子束,而是使用可以单独控制发光或阻挡光的像素矩阵。这使得图像更加清晰,刷新率更快,能源效率也得到了提高。

    然而,刷新显示的基本概念并没有发生很大变化。显示内容仍然通过向每个像素发送信号来控制其亮度和颜色来进行更新。这些信号由显示控制器根据输入视频信号生成,并且它们确定屏幕上显示的内容。

    1.2 LCD示意图

    下图是LCD示意图,里面的每个点就是一个像素点。它里面有一个电子枪,一边移动,一边发出各种颜色的光。用动态图表示如下:

    img

    电子枪是如何移动的?

    • 有一条Pixel Clock时钟线与LCD相连,每发出一次Pixel Clock,电子枪就移动一个像素。

    颜色如何确定?

    • 由连接LCD的三组线RGB三原色混合而成:R(Red)、G(Green)、B(Blue)确定。

    电子枪如何得知应跳到下一行?

    • 有一条HSYNC信号线与LCD相连,每发出一次脉冲(高低电平),电子枪就跳到下一行,该信号叫做行同步信号。

    电子枪如何得知应跳到原点?

    • 有一条VSYNC信号线与LCD相连,每发出一次脉冲(高低电平),电子枪就跳到原点,该信号叫做帧同步信号。

    RGB线上的数据从何而来?

    • 内存里面划分一块显存(FrameBuffer),里面存放了要显示的数据,LCD控制器(比如RK3399VOP)从里面将数据读出来,通过显示接口(比如mipilvdshdmiedp、``dp)传给电子枪,电子枪再依次打到显示屏上。
    img

    因此要想在显示设备上显示图像,至少需要3个信号:

    • Pixel Clock:时钟信号,在每个时钟周期更新屏幕上一个像素;
    • HSYNC:水平同步信号,引脚每发出一个脉冲,表示一行的数据开始发送;
    • VSYNC:垂直同步信号,引脚每发出一个脉冲,表示一帧的数据开始发送。
    1.3 时序参数

    在上图中我们发现除了Pixel ClockHSYNCVSYNC信号外,还包含了大量的时序参数,这里我们一一介绍:

    • HBPD(hback porch):行同步信号的后肩,单位为1个Pixel Clock时钟周期;
    • HFPD(hfront porch):行同步信号的前肩,单位为1个Pixel Clock时钟周期;
    • HSPW(hsync pulse):行同步信号的脉宽,单位为1个Pixel Clock时钟周期;
    • HOZVAL(hdisplay):LCD的水平宽度;
    • VBPD(vback porch):帧同步信号的后肩,单位为1个HSYNC时钟周期;
    • VFPD(vfront porch):帧同步信号的前肩,单位为1个HSYNC时钟周期;
    • VSPW(vsync pulse):帧同步信号的脉宽,单位为1个HSYNC时钟周期;
    • LINEVAL (vdisplay):LCD的垂直宽度;

    如果这部分内容看不到,可以参考我之前写的这篇文章:Mini2440裸机开发之LCD基础

    二、CRTC核心数据结构

    DRM框架中,CRTCFramebuffer中读取待显示的图像,并按照响应的格式输出给encoder,其主要承担的作用为:

    • 配置适合显示的显示模式、分辨率、刷新率等参数,并输出相应的时序;
    • 扫描Framebuffer发送到一个或多个显示器;
    • 更新Framebuffer

    概括下就是,对显示器进行扫描,产生时序信号的模块、负责帧切换、电源控制、色彩调整等等。

    2.1 struct drm_crtc

    linux内核使用struct drm_crtc来表示一个CRTC控制器,包括显示模式、分辨率、刷新率等参数。定义在include/drm/drm_crtc.h

    1. /**
    2. * struct drm_crtc - central CRTC control structure
    3. *
    4. * Each CRTC may have one or more connectors associated with it. This structure
    5. * allows the CRTC to be controlled.
    6. */
    7. struct drm_crtc {
    8. /** @dev: parent DRM device */
    9. struct drm_device *dev;
    10. /** @port: OF node used by drm_of_find_possible_crtcs(). */
    11. struct device_node *port;
    12. /**
    13. * @head:
    14. *
    15. * List of all CRTCs on @dev, linked from &drm_mode_config.crtc_list.
    16. * Invariant over the lifetime of @dev and therefore does not need
    17. * locking.
    18. */
    19. struct list_head head;
    20. /** @name: human readable name, can be overwritten by the driver */
    21. char *name;
    22. /**
    23. * @mutex:
    24. *
    25. * This provides a read lock for the overall CRTC state (mode, dpms
    26. * state, ...) and a write lock for everything which can be update
    27. * without a full modeset (fb, cursor data, CRTC properties ...). A full
    28. * modeset also need to grab &drm_mode_config.connection_mutex.
    29. *
    30. * For atomic drivers specifically this protects @state.
    31. */
    32. struct drm_modeset_lock mutex;
    33. /** @base: base KMS object for ID tracking etc. */
    34. struct drm_mode_object base;
    35. /**
    36. * @primary:
    37. * Primary plane for this CRTC. Note that this is only
    38. * relevant for legacy IOCTL, it specifies the plane implicitly used by
    39. * the SETCRTC and PAGE_FLIP IOCTLs. It does not have any significance
    40. * beyond that.
    41. */
    42. struct drm_plane *primary;
    43. /**
    44. * @cursor:
    45. * Cursor plane for this CRTC. Note that this is only relevant for
    46. * legacy IOCTL, it specifies the plane implicitly used by the SETCURSOR
    47. * and SETCURSOR2 IOCTLs. It does not have any significance
    48. * beyond that.
    49. */
    50. struct drm_plane *cursor;
    51. /**
    52. * @index: Position inside the mode_config.list, can be used as an array
    53. * index. It is invariant over the lifetime of the CRTC.
    54. */
    55. unsigned index;
    56. /**
    57. * @cursor_x: Current x position of the cursor, used for universal
    58. * cursor planes because the SETCURSOR IOCTL only can update the
    59. * framebuffer without supplying the coordinates. Drivers should not use
    60. * this directly, atomic drivers should look at &drm_plane_state.crtc_x
    61. * of the cursor plane instead.
    62. */
    63. int cursor_x;
    64. /**
    65. * @cursor_y: Current y position of the cursor, used for universal
    66. * cursor planes because the SETCURSOR IOCTL only can update the
    67. * framebuffer without supplying the coordinates. Drivers should not use
    68. * this directly, atomic drivers should look at &drm_plane_state.crtc_y
    69. * of the cursor plane instead.
    70. */
    71. int cursor_y;
    72. /**
    73. * @enabled:
    74. *
    75. * Is this CRTC enabled? Should only be used by legacy drivers, atomic
    76. * drivers should instead consult &drm_crtc_state.enable and
    77. * &drm_crtc_state.active. Atomic drivers can update this by calling
    78. * drm_atomic_helper_update_legacy_modeset_state().
    79. */
    80. bool enabled;
    81. /**
    82. * @mode:
    83. *
    84. * Current mode timings. Should only be used by legacy drivers, atomic
    85. * drivers should instead consult &drm_crtc_state.mode. Atomic drivers
    86. * can update this by calling
    87. * drm_atomic_helper_update_legacy_modeset_state().
    88. */
    89. struct drm_display_mode mode;
    90. /**
    91. * @hwmode:
    92. *
    93. * Programmed mode in hw, after adjustments for encoders, crtc, panel
    94. * scaling etc. Should only be used by legacy drivers, for high
    95. * precision vblank timestamps in
    96. * drm_crtc_vblank_helper_get_vblank_timestamp().
    97. *
    98. * Note that atomic drivers should not use this, but instead use
    99. * &drm_crtc_state.adjusted_mode. And for high-precision timestamps
    100. * drm_crtc_vblank_helper_get_vblank_timestamp() used
    101. * &drm_vblank_crtc.hwmode,
    102. * which is filled out by calling drm_calc_timestamping_constants().
    103. */
    104. struct drm_display_mode hwmode;
    105. /**
    106. * @x:
    107. * x position on screen. Should only be used by legacy drivers, atomic
    108. * drivers should look at &drm_plane_state.crtc_x of the primary plane
    109. * instead. Updated by calling
    110. * drm_atomic_helper_update_legacy_modeset_state().
    111. */
    112. int x;
    113. /**
    114. * @y:
    115. * y position on screen. Should only be used by legacy drivers, atomic
    116. * drivers should look at &drm_plane_state.crtc_y of the primary plane
    117. * instead. Updated by calling
    118. * drm_atomic_helper_update_legacy_modeset_state().
    119. */
    120. int y;
    121. /** @funcs: CRTC control functions */
    122. const struct drm_crtc_funcs *funcs;
    123. /**
    124. * @gamma_size: Size of legacy gamma ramp reported to userspace. Set up
    125. * by calling drm_mode_crtc_set_gamma_size().
    126. *
    127. * Note that atomic drivers need to instead use
    128. * &drm_crtc_state.gamma_lut. See drm_crtc_enable_color_mgmt().
    129. */
    130. uint32_t gamma_size;
    131. /**
    132. * @gamma_store: Gamma ramp values used by the legacy SETGAMMA and
    133. * GETGAMMA IOCTls. Set up by calling drm_mode_crtc_set_gamma_size().
    134. *
    135. * Note that atomic drivers need to instead use
    136. * &drm_crtc_state.gamma_lut. See drm_crtc_enable_color_mgmt().
    137. */
    138. uint16_t *gamma_store;
    139. /** @helper_private: mid-layer private data */
    140. const struct drm_crtc_helper_funcs *helper_private;
    141. /** @properties: property tracking for this CRTC */
    142. struct drm_object_properties properties;
    143. /**
    144. * @scaling_filter_property: property to apply a particular filter while
    145. * scaling.
    146. */
    147. struct drm_property *scaling_filter_property;
    148. /**
    149. * @state:
    150. *
    151. * Current atomic state for this CRTC.
    152. *
    153. * This is protected by @mutex. Note that nonblocking atomic commits
    154. * access the current CRTC state without taking locks. Either by going
    155. * through the &struct drm_atomic_state pointers, see
    156. * for_each_oldnew_crtc_in_state(), for_each_old_crtc_in_state() and
    157. * for_each_new_crtc_in_state(). Or through careful ordering of atomic
    158. * commit operations as implemented in the atomic helpers, see
    159. * &struct drm_crtc_commit.
    160. */
    161. struct drm_crtc_state *state;
    162. /**
    163. * @commit_list:
    164. *
    165. * List of &drm_crtc_commit structures tracking pending commits.
    166. * Protected by @commit_lock. This list holds its own full reference,
    167. * as does the ongoing commit.
    168. *
    169. * "Note that the commit for a state change is also tracked in
    170. * &drm_crtc_state.commit. For accessing the immediately preceding
    171. * commit in an atomic update it is recommended to just use that
    172. * pointer in the old CRTC state, since accessing that doesn't need
    173. * any locking or list-walking. @commit_list should only be used to
    174. * stall for framebuffer cleanup that's signalled through
    175. * &drm_crtc_commit.cleanup_done."
    176. */
    177. struct list_head commit_list;
    178. /**
    179. * @commit_lock:
    180. *
    181. * Spinlock to protect @commit_list.
    182. */
    183. spinlock_t commit_lock;
    184. /**
    185. * @debugfs_entry:
    186. *
    187. * Debugfs directory for this CRTC.
    188. */
    189. struct dentry *debugfs_entry;
    190. /**
    191. * @crc:
    192. *
    193. * Configuration settings of CRC capture.
    194. */
    195. struct drm_crtc_crc crc;
    196. /**
    197. * @fence_context:
    198. *
    199. * timeline context used for fence operations.
    200. */
    201. unsigned int fence_context;
    202. /**
    203. * @fence_lock:
    204. *
    205. * spinlock to protect the fences in the fence_context.
    206. */
    207. spinlock_t fence_lock;
    208. /**
    209. * @fence_seqno:
    210. *
    211. * Seqno variable used as monotonic counter for the fences
    212. * created on the CRTC's timeline.
    213. */
    214. unsigned long fence_seqno;
    215. /**
    216. * @timeline_name:
    217. *
    218. * The name of the CRTC's fence timeline.
    219. */
    220. char timeline_name[32];
    221. /**
    222. * @self_refresh_data: Holds the state for the self refresh helpers
    223. *
    224. * Initialized via drm_self_refresh_helper_init().
    225. */
    226. struct drm_self_refresh_data *self_refresh_data;
    227. };

    该结构体包含以下成员变量:

    • dev:该CRTC所属的DRM设备;
    • port:设备节点,被drm_of_find_possible_crtcs()使用;
    • head:链表节点,用于将当前节点添加到&drm_mode_config.crtc_list链表;
    • name:名称,可以被驱动程序覆盖;
    • mutex:用于保护CRTC状态的互斥锁;
    • basestruct drm_mode_object
    • primary:与该CRTC相关的primary plane
    • cursor:与该CRTC相关的cursor plane
    • index:在mode_config.list中的位置,可以用作数组索引;
    • cursor_x:光标的x坐标;
    • cursor_y:光标的y坐标;
    • enabled:指示该CRTC是否已启用;
    • mode:当前模式时序信息;
    • hwmode:硬件中编程的模式;
    • x:在屏幕上的x坐标;
    • y:在屏幕上的y坐标;
    • funcsCRTC控制函数;
    • gamma_size:报告给用户空间的legacy gamma ramp大小;
    • gamma_storelegacy gamma values数据存储区域;
    • helper_private:中间层私有数据;
    • properties:跟踪该CRTC的属性;
    • scaling_filter_property:应用于缩放时的特定滤镜的属性;
    • state:当前CRTC的原子状态;
    • commit_list:跟踪挂起提交的列表;
    • commit_lock:保护commit_list的自旋锁;
    • debugfs_entry:用于调试的目录条目;
    • crcCRC捕获的配置设置;
    • fence_context:用于围栏操作的时间线上下文;
    • fence_lock:保护时间线上的围栏的自旋锁;
    • fence_seqno:用作CRTC时间线上创建的围栏的单调计数器;
    • timeline_nameCRTC时间线的名称;
    • self_refresh_data:保存自刷新辅助程序状态的数据;
    2.1.1 struct drm_display_mode

    struct drm_display_mode用于表示显示模式,包含了显示的何种时序参数。定义在include/drm/drm_modes.h

    1. /**
    2. * struct drm_display_mode - DRM kernel-internal display mode structure
    3. * @hdisplay: horizontal display size
    4. * @hsync_start: horizontal sync start
    5. * @hsync_end: horizontal sync end
    6. * @htotal: horizontal total size
    7. * @hskew: horizontal skew?!
    8. * @vdisplay: vertical display size
    9. * @vsync_start: vertical sync start
    10. * @vsync_end: vertical sync end
    11. * @vtotal: vertical total size
    12. * @vscan: vertical scan?!
    13. * @crtc_hdisplay: hardware mode horizontal display size
    14. * @crtc_hblank_start: hardware mode horizontal blank start
    15. * @crtc_hblank_end: hardware mode horizontal blank end
    16. * @crtc_hsync_start: hardware mode horizontal sync start
    17. * @crtc_hsync_end: hardware mode horizontal sync end
    18. * @crtc_htotal: hardware mode horizontal total size
    19. * @crtc_hskew: hardware mode horizontal skew?!
    20. * @crtc_vdisplay: hardware mode vertical display size
    21. * @crtc_vblank_start: hardware mode vertical blank start
    22. * @crtc_vblank_end: hardware mode vertical blank end
    23. * @crtc_vsync_start: hardware mode vertical sync start
    24. * @crtc_vsync_end: hardware mode vertical sync end
    25. * @crtc_vtotal: hardware mode vertical total size
    26. *
    27. * This is the kernel API display mode information structure. For the
    28. * user-space version see struct drm_mode_modeinfo.
    29. *
    30. * The ho
  • 相关阅读:
    热忱与专业齐飞 | 微软最有价值专家项目,广纳微软技术贡献者!
    【PostgreSQL内核学习(十六)—— (pg_statistic 表)】
    利用Pycharm将python文件打包为exe文件
    pytorch 入门(二)
    从字符串中提取数字并重新编号
    Windows网络管理及诊断命令整理
    【C语言】排序算法 -------- 计数排序
    服务器中如何检查端口是否开放
    开发好APP了如何上架apple store市场
    Java this关键字详解(3种用法)
  • 原文地址:https://blog.csdn.net/Graceful_scenery/article/details/133984689