基于DRM框架的HDMI热插拔流程分析

本文详细介绍了基于DRM框架的HDMI热插拔流程,从更新物理层状态、检测连接器状态到触发KMS事件,再到用户空间的udevd和Xorg如何响应。在实验环境中,使用了GDK8开发平台和挥码枪进行硬件调试。
摘要由CSDN通过智能技术生成

基于DRM框架的HDMI热插拔流程分析

1. DRM介绍

DRM 全称是Direct Rendering Manager,进行显示输出管理、buffer 分配、帧缓冲。对应userspace 库
为libdrm,,libdrm 库提供了一系列友好的控制封装,使用户可以方便的进行显示的控制和buffer 申请。

GDK8使用的是瑞芯微的RK3328芯片,而瑞芯微的显示框架有两大模块,分别是DRM与FB,其中FB框架是对应3.x内核的,而DRM框架是对应4.x内核,因此使用4.19.161内核的GDK8就是采用基于DRM显示框架的HDMI。

DRM的设备节点为"/dev/dri/cardX", X 为0-15 的数值,默认使用的是/dev/dri/card0

CRTC:显示控制器,在rockchip 平台是SOC 内部VOP(部分文档也称为LCDC)模块的抽象;
Plane:图层,在rockchip 平台是SOC 内部VOP(LCDC)模块win 图层的抽象;
Encoder:输出转换器,指RGB、LVDS、DSI、eDP、HDMI、CVBS、VGA 等显示接口;
Connector:连接器,指encoder 和panel 之间交互的接口部分;
Bridge:桥接设备,一般用于注册encoder 后面另外再接的转换芯片,如DSI2HDMI 转换芯片。
Panel:泛指屏,各种LCD、HDMI 等显示设备的抽象;
GEM:buffer 管理和分配,类似android 下的ion。

2. 热插拔介绍

热插拔是指在不关闭系统的前提下,插拔外部设备而不影响系统的正常使用。这个功能对需要许多外设都是非常重要的,毕竟你不可能希望拔出HDMI后,只能关机插入HDMI,再重新上电后,才能让HDMI再次工作。

DRM驱动处理热插拔的过程比较复杂,下面会对一些主要的函数设置断点,并分析其的作用。

3. HDMI热插拔流程分析

3.1 更新物理层状态

当内核检测到HDMI热插拔事件后,首先会通过dw_hdmi_phy_update_hpd函数更改hdmi的phy状态。

void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
			    bool force, bool disabled, bool rxsense)
{
   
	u8 old_mask = hdmi->phy_mask;

	if (force || disabled || !rxsense)
		hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
	else
		hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;

	if (old_mask != hdmi->phy_mask)
		hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
}
EXPORT_SYMBOL_GPL(dw_hdmi_phy_update_hpd);

在用户空间中,可以通过dw-hdmi目录下的虚文件,查看HDMI的状态信息。

cat /sys/kernel/debug/dw-hdmi/status
PHY: enabled                    Mode: HDMI
Pixel Clk: 297000000Hz          TMDS Clk: 297000000Hz
Color Format: YUV444            Color Depth: 8 bit
Colorimetry: ITU.BT709          EOTF: Off

Mode:当前的输出模式
Pixel Clk:当前输出的像素时钟
TMDS Clk:当前输出的HDMI符号率
Color Format:当前输出的颜色格式
Color Depth:当前输出的颜色深度
Colorimery:当前输出的颜色标准
EOTF:HDR信息

通过栈回溯可以看到,在内核检测到HDMI插拔时,内核会检测到中断事件,并创建一个新的线程来处理该事件,这个时候内核会调用dw_hdmi_irq,在dw_hdmi_irq内会去更新hdmi的phy和rxsense的状态。

kn
 # Child-SP          RetAddr           Call Site
00 ffffff80`0a9b3d20 ffffff80`087f17d8 lk!dw_hdmi_phy_update_hpd [drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @ 1730]
01 ffffff80`0a9b3d20 ffffff80`087f1a1c lk!dw_hdmi_setup_rx_sense+0x78 [drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @ 3178]
02 ffffff80`0a9b3d20 ffffff80`08129238 lk!dw_hdmi_irq+0x22c [drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @ 3219]
03 ffffff80`0a9b3d20 ffffff80`08129618 lk!irq_thread_fn+0x28 [kernel/irq/manage.c @ 1010]
04 ffffff80`0a9b3d20 ffffff80`080e168c lk!irq_thread+0x118 [kernel/irq/manage.c @ 1091]
05 ffffff80`0a9b3d20 ffffff80`08085dd0 lk!kthread+0x12c [kernel/kthread.c @ 260]
06 ffffff80`0a9b3d20 00000008`00000008 lk!ret_from_fork+0x10 [arch/arm64/kernel/entry.S @ 1104]

3.2 检测连接器状态

drm驱动通过drm_helper_hpd_irq_event函数检测每一个connector的状态。
通过下面的栈回溯可以看到当HDMI插入后,内核同样会检测到中断事件,并创建一个新的线程来处理该事件,在更新完phy和rxsense的状态后,由于是热插拔事件,所以会调用repo_hpd_event函数(hpd:hot plug detect)。

kn
 # Child-SP          RetAddr           Call Site
00 ffffff80`0abd3d60 ffffff80`087f241c lk!drm_helper_hpd_irq_event [drivers/gpu/drm/drm_probe_helper.c @ 773]
01 ffffff80`0abd3d60 ffffff80`080db1b8 lk!repo_hpd_event+0x8c [drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @ 383]
02 ffffff80`0abd3d60 ffffff80`080db47c lk!process_one_work+0x1a0 [./arch/arm64/include/asm/jump_label.h @ 31]
03 ffffff80`0abd3d60 ffffff80`080e168c lk!worker_thread+0x4c [./include/linux/compiler.h @ 193]
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值