RK平台Uboot HDMI驱动分析与补丁详解

电子说

1.4w人已加入

描述

本文基于RK3576等芯片Uboot下的dw_hdmi.c/h驱动源码,完整拆解HDMI数据处理全流程,分析补丁的根因、解决的问题,以及受影响的芯片范围。

一、Uboot下RK HDMI驱动整体架构

RK平台Uboot的HDMI驱动基于Synopsys DesignWare HDMI TX控制器(DW HDMI)开发,分为4个核心层级,全链路适配RK系列芯片的显示需求:

1.连接器抽象层:对接Uboot显示框架,统一热插拔、EDID解析、模式选择、显示使能/禁用的标准接口;

2.DW HDMI核心驱动层:dw_hdmi.c/h为核心,实现控制器寄存器配置、PHY控制、音视频数据处理、EDID读写、色彩空间转换(CSC)、InfoFrame配置、HDCP加密等核心逻辑;

3.PHY适配层:兼容Synopsys原厂HDMI PHY与RK自研Inno HDMI PHY,实现PLL配置、TMDS信号控制、电源管理;

4.平台适配层:对接RK芯片的GRF系统控制器、GPIO、时钟、DDC I2C总线,完成引脚复用、资源映射。

二、HDMI全流程数据处理详解

RK HDMI从初始化到画面输出,分为7个核心阶段,完整数据流与执行逻辑如下:

HDMI

阶段1:

驱动初始化与硬件资源准备(rockchip_dw_hdmi_init

该阶段为Uboot显示子系统启动时的入口,完成硬件与驱动的基础初始化:

1.内存与结构体初始化:申请struct dw_hdmi核心控制结构体、EDID显示模式缓冲区的内存,完成清零初始化;

2.平台资源解析

○读取设备树(DTS)配置,解析HDMI寄存器基地址、寄存器访问位宽、HPD热插拔GPIO、DDC总线时序、PHY配置、HDCP使能等参数;

○映射GRF系统控制器寄存器,用于HDMI引脚复用、VOP显示通路选择;

○根据寄存器位宽配置读写函数,1字节位宽使用dw_hdmi_writeb/readb,4字节位宽使用dw_hdmi_writel/readl,适配不同RK芯片的寄存器访问规范。

3.DDC I2C总线初始化:配置DDC总线时钟分频、SCL高低电平时长,符合I2C标准模式(100KHz),复位I2C控制器,清空中断状态,为EDID读取做准备;

4.PHY检测与适配:读取HDMI_CONFIG2_ID寄存器识别PHY类型,匹配对应的驱动操作集(原厂PHY用dw_hdmi_synopsys_phy_ops,RK Inno PHY用自定义ops);

5.控制器核心初始化:读取控制器版本号,屏蔽所有非必要中断(仅保留HPD热插拔中断),关闭无关模块时钟,强制输出黑屏避免初始化异常画面。

阶段2:

热插拔检测与连接状态判断(rockchip_dw_hdmi_detect

该阶段执行于初始化后,也用于周期性轮询,核心是判断HDMI线缆连接状态:

1.读取PHY状态寄存器HDMI_PHY_STAT0的HDMI_PHY_HPD位,HPD高电平为显示器已连接;

2.若外接HDMI桥接芯片,同步调用桥接芯片的检测函数,确认链路完整性;

3.返回连接状态,未连接则终止后续显示流程。

阶段3:

EDID数据读取与解析(rockchip_dw_hdmi_get_timing

该阶段是显示模式匹配的核心,也是本次补丁修改的关键函数,核心数据流如下:

1.EDID数据读取:调用drm_do_get_edid,通过DDC I2C总线执行dw_hdmi_i2c_xfer读写,从显示器读取128字节为块的EDID数据,动态分配内存并存储到conn_state->edid;

2.EDID有效性校验与能力解析

○若EDID读取成功:

i.调用drm_detect_monitor_audio(edid),解析EDID音频能力块,赋值hdmi->sink_has_audio;

ii.调用drm_detect_hdmi_monitor(edid),解析EDID的HDMI厂商数据块,区分HDMI/DVI显示器,赋值hdmi->sink_is_hdmi;

iii.调用drm_add_edid_modes,从EDID解析所有支持的显示模式(分辨率、刷新率、时序参数),存入模式缓冲区。

○若EDID读取失败:

i.强制设置sink_is_hdmi = true、sink_has_audio = true,兼容无EDID的显示器;

ii.加载默认CEA标准模式(720P、1080P等常用分辨率),设置首选显示模式。

3.显示模式过滤与排序:过滤超出控制器/PHY/VOP能力的模式(如像素时钟超限),按分辨率、刷新率优先级排序,确定最终首选模式preferred_mode。

阶段4:

输出格式与色彩空间配置

基于EDID解析结果,配置输出链路的核心参数:

1.选择输出总线格式:根据显示器能力,确定RGB/YUV444/YUV422/YUV420输出格式,以及8bit/10bit/12bit色深;

2.配置色彩编码与量化范围:根据CEA模式VIC选择BT.601/BT.709/BT.2020色彩编码,设置全范围(Full Range)/有限范围(Limited Range)量化参数;

3.配置VOP输出模式,匹配HDMI的数据通路与引脚复用。

阶段5:

HDMI链路与模式硬件配置(dw_hdmi_setup

该阶段是控制器核心配置环节,将显示模式转化为寄存器配置,完成全链路硬件使能:

1.音视频时序计算(hdmi_av_composer

○解析显示时序的有效区、消隐区、同步前后沿、同步极性,计算像素时钟与TMDS时钟(根据色深和格式调整,如10bit RGB为像素时钟×5/4,YUV420为像素时钟/2);

○高带宽场景(TMDS时钟>340MHz)通过SCDC寄存器配置显示器开启TMDS加扰,保证信号完整性;

○写入帧合成器(FC)时序寄存器,配置输入视频参数与DVI/HDMI模式。

2.PHY配置与上电(hdmi_phy_configure

○先下电PHY并执行复位,根据像素时钟配置PLL参数、终端电阻、电压摆率;

○配置完成后上电PHY,等待PLL锁定(HDMI_PHY_STAT0的TX_PHY_LOCK位),锁定失败返回超时错误。

3.视频通路使能(dw_hdmi_enable_video_path

○开启像素时钟、TMDS时钟、CSC模块时钟;

○配置TMDS通道前导码、控制周期时长,保证HDMI信号合规性;

○根据输入/输出色彩空间,配置CSC模块旁路或使能。

4.音频时钟再生配置:若显示器支持音频,根据采样率(默认48KHz)和TMDS时钟计算N/CTS值,写入音频寄存器实现时钟同步,开启音频通路。

5.InfoFrame配置

○HDMI与DVI的核心差异在于InfoFrame,HDMI通过AVI InfoFrame传递色彩空间、量化范围、分辨率等信息,DVI不支持该特性;

○填充AVI InfoFrame并写入寄存器,配置色彩参数、内容类型(游戏/影院/图形);4K/3D场景额外配置厂商特定InfoFrame。

6.视频数据全链路配置

○视频采样模块:配置输入数据映射格式,消隐期数据填充规则;

○CSC色彩空间转换模块:配置插值/抽取模式,写入色彩转换系数矩阵(如BT601/BT709与RGB互转、全范围转有限范围);

○视频打包模块:配置像素重复、色深处理、数据打包格式,将并行视频数据转为TMDS链路所需格式。

7.HDCP配置:若开启HDCP1.x,从厂商存储区读取密钥,配置HDCP控制器,完成认证与加密流程。

8.溢出修复:针对不同版本的DW控制器,执行TMDS软件复位,修复寄存器写入溢出问题,保证配置生效。

阶段6:

显示使能与输出(rockchip_dw_hdmi_enable

保存当前显示模式,执行全链路配置后使能视频输出,显示器接收信号并渲染画面。

阶段7:

禁用与下电(rockchip_dw_hdmi_disable

禁用PHY、下电TMDS发送器、关闭模块时钟、屏蔽中断,进入低功耗模式。

三、补丁详细分析

1. 补丁修改点

 

diff --git a/drivers/video/drm/dw_hdmi.c b/drivers/video/drm/dw_hdmi.cindex 6bdee673b55..41bd5122c7a 100644--- a/drivers/video/drm/dw_hdmi.c+++ b/drivers/video/drm/dw_hdmi.c@@ -2635,13 +2635,14 @@ int rockchip_dw_hdmi_get_timing(struct rockchip_connector *conn, struct display_ int ret = 0, i, vic; struct connector_state *conn_state = &state->conn_state; struct dw_hdmi *hdmi = conn->data;-struct edid *edid = (struct edid *)conn_state->edid;+struct edid *edid;+const u8 def_modes_vic[6] = {4, 16, 2, 17, 31, 19};
 if (!hdmi) return -EFAULT;
 conn_state->edid = drm_do_get_edid(&hdmi->adap);+edid = (struct edid *)conn_state->edid;
 if (conn_state->edid) { hdmi->sink_has_audio = drm_detect_monitor_audio(edid);

 

2. 根因分析

1.空指针赋值时序错误:conn_state->edid是动态分配的内存,仅当执行drm_do_get_edid后才会完成内存分配与EDID数据写入;修改前在函数开头就将edid指针赋值为conn_state->edid,此时该指针为NULL,后续即使drm_do_get_edid执行成功,edid指针仍为NULL,不会同步更新。

2.HDMI/DVI模式误判:drm_detect_hdmi_monitor(edid)传入NULL指针,函数执行失败并返回false,导致hdmi->sink_is_hdmi = false,驱动将HDMI显示器错误识别为DVI显示器。

3.紫屏故障触发逻辑:DVI仅支持RGB格式,不支持YUV格式与AVI InfoFrame;当驱动误判为DVI模式时,会关闭InfoFrame发送,若此时输出格式为YUV(RK平台默认常用配置),显示器将YUV数据按RGB格式解析,最终出现色彩完全错乱的紫屏、花屏。

4.附加风险:空指针访问还可能导致Uboot崩溃、HDMI音频功能异常、显示模式识别错误等问题。

3. 补丁解决的核心问题

1.修复空指针访问,调整edid指针赋值时序,保证EDID读取完成后再给指针赋值,确保指针有效性;

2.修复HDMI/DVI模式误判,drm_detect_hdmi_monitor可正常解析EDID数据,正确识别HDMI显示器;

3.彻底解决YUV输出紫屏问题:正确识别HDMI模式后,驱动正常发送AVI InfoFrame,显示器可正确解析YUV/RGB格式,避免色彩错乱;

4.提升显示器兼容性,修复EDID读取成功但显示异常的问题,兼容更多电视、拼接屏、商用显示器等HDMI终端。

四、受影响的芯片范围与原因

1. 受影响芯片

RK3576、RK3399、RK3328、RK3228、RK3229、RK3288、RK3399Pro、RK3568、RK3566、RK3528,所有使用Synopsys DesignWare HDMI 2.0 TX控制器的瑞芯微芯片

2. 受影响的核心原因

1.驱动代码共用:上述芯片的Uboot HDMI驱动完全共用dw_hdmi.c核心代码,rockchip_dw_hdmi_get_timing函数的时序bug存在于全平台;

2.控制器架构一致:所有芯片均集成Synopsys DW HDMI TX控制器,驱动逻辑与bug触发条件完全一致;

3.输出格式特性:RK中高端芯片默认优先使用YUV格式输出,更容易触发紫屏问题;低端芯片即使默认RGB输出,也存在模式误判、HDMI音频/高级功能失效的问题;

4.Uboot版本迭代影响:该bug出现在conn_state->edid改为动态内存分配的Uboot版本,所有升级到该版本的RK平台均会受影响。

五、补丁的应用场景与价值

1.Uboot启动画面保障:修复Uboot阶段HDMI紫屏、无画面问题,保证启动logo、升级界面、命令行界面正常显示;

2.工厂产线适配:避免产线烧录、整机测试时出现批量HDMI显示异常,提升生产良率;

3.系统Recovery/OTA升级:保证安卓/Linux系统Recovery模式、OTA升级界面正常显示,避免用户无法操作的故障;

4.工业嵌入式场景:适配基于Uboot的裸机显示、工业控制场景,保证HDMI输出稳定,避免无画面、色彩异常问题;

5.终端兼容性提升:修复对EDID时序特殊的显示器的兼容性,解决“有信号但无画面/紫屏”的行业常见问题。

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分