当前位置:首页 > 显示光电 > 显示光电
[导读]嵌入式Linux跑HDMI不是“设备树配一下就有画面”,4K下更是带宽、时序、EDID、色彩管线一起卡。稳定输出靠DRM/KMS把CRTC→Encoder→Bridge→Connector串对,色彩校准靠CRTC层的DEGAMMA_LUT/CTM/GAMMA_LUT,不是用户态随便贴个ICC文件。


嵌入式Linux跑HDMI不是“设备树配一下就有画面”,4K下更是带宽、时序、EDID、色彩管线一起卡。稳定输出靠DRM/KMS把CRTC→Encoder→Bridge→Connector串对,色彩校准靠CRTC层的DEGAMMA_LUT/CTM/GAMMA_LUT,不是用户态随便贴个ICC文件。

一、DRM管道先打通

HDMI输出在内核里是一条display pipeline:

VOP/Display Controller(CRTC) → Encoder → Bridge(ADV7533/LT8912) → Connector(HDMI-A)

桥接芯片(MIPI-DSI转HDMI或SOC内置HDMI TX)必须在设备树里用remote-endpoint把两端连起来,否则probe时drm_bridge_attach返回-517,屏幕永远不亮。

以LT8912为例核心节点:

&i2c {

 lt8912@48 {

   compatible = "lontium,lt8912b";

   reset-gpios = <&gpio 12 GPIO_ACTIVE_LOW>;

   ports {

     port@0 { lt_in: endpoint { remote-endpoint = <&dsi_out>; data-lanes = <1 2 3 4>; }; };

     port@1 { lt_out: endpoint { remote-endpoint = <&hdmi_conn>; }; };

   };

 };

};

hdmi_out: connector {

 compatible = "hdmi-connector";

 type = "a";

 port { endpoint { remote-endpoint = <&lt_out>; }; };

};

DSI lanes数、reset脚、I2C地址三者任一错都点不亮。

二、4K@60稳定输出的带宽前提

HDMI 2.0 TMDS总带宽18Gbps,8b/10b后可用约14.4Gbps。4K60(3840×2160@60)像素时钟594MHz:

8bit RGB/4:4:4:能进

10bit HDR 4:4:4:超带宽,必须降成YUV 4:2:0或4:2:2

HDMI 2.1 FRL才扛得住4K120/4:4:4 HDR

驱动侧常踩的坑:

EDID只解析出1080p → drm_do_add_edid_modes没加4K VIC,或屏线不达高速认证

像素时钟PLL精度超±0.5% → 花屏/闪断

默认走RGB却没降采样 → 模式直接被atomic_check拒掉

HPD中断没消抖 → 插拔瞬间重复重协商

用户态验证:

cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode

modetest -M rockchip -s  HDMI-A-1:3840x2160@60

进不了4K60先看EDID有没有VIC 107/97,再看dmesg里phy时钟报错。

三、驱动里该开的色彩能力

色彩校准不是在应用层做矩阵乘法再写framebuffer——那样每帧都算、还覆盖不了硬件输出。正确用法是CRTC颜色属性:

drm_crtc_enable_color_mgmt(crtc,

   degamma_lut_size,

   has_ctm ? sizeof(struct drm_color_ctm) : 0,

   gamma_lut_size);

内核提供三条硬件块:DEGAMMA_LUT → CTM(3x3矩阵)→ GAMMA_LUT,属性为blob,atomic提交时生效。

DEGAMMA_LUT:把屏的非线性响应拉回线性

CTM:白点偏移、色域映射(BT.709↔面板实际原色)、饱和度调整

GAMMA_LUT:输出级gamma/亮度曲线校正

用户空间用libdrm拼blob:

drmModeCreatePropertyBlob(fd, gamma_table, size, &blob_id);

drmModeObjectSetProperty(fd, crtc_id, DRM_MODE_OBJECT_CRTC,

                        gamma_prop_id, blob_id);

CTM用S31.32定点格式填struct drm_color_ctm,别直接扔float。

四、校准数据从哪来

工程做法:

出厂用色度计测面板RGB三原色+白点

算出degamma/gamma曲线和3x3 CTM

存成设备专属lut文件(/etc/hdmi_cal/xxx.bin)

启动脚本或compositor在输出绑定时下发CRTC属性

别把校准写死在驱动里——换屏批次就要重编内核。驱动只负责“支持LUT/CTM、暴露SIZE属性”,数据交给用户态。

五、原子提交顺序

色彩属性和mode必须同一次atomic commit:

set CRTC MODE_ID

set DEGAMMA_LUT blob

set CTM blob

set GAMMA_LUT blob

drm_atomic_commit()

分开设会闪一下;LUT尺寸和驱动声明不一致直接-EINVAL。

六、落坑清单

只开GAMMA不开DEGAMMA → 线性空间算错,色偏

CTM写成float数组 → 硬件当定点解,颜色炸掉

LUT尺寸硬写256,驱动实际支持512 → 提交失败

4K60强行RGB10bit → 带宽不够降频到30Hz

桥接芯片端口没remote-endpoint → probe失败-517

HPD不消抖 → 开机偶发黑屏

校准数据全局生效 → 多屏时副屏偏色,必须按connector绑定

在应用层做色彩转换 → GPU合成后再覆盖,功耗白费

七、落地顺序

设备树bridge/connector端点连通,modetest出图

EDID确认4K VIC,像素时钟对得上

色彩格式按带宽选RGB或YUV420

驱动drm_crtc_enable_color_mgmt暴露属性

出厂标定生成degamma/ctm/gamma

用户态atomic一次性下发

示波器看TMDS眼图,确认长距离不降频

嵌入式Linux HDMI的4K稳定输出,本质是“带宽匹配+时序准确+EDID诚实地给模式”;色彩校准则是把校正从软件合成挪到显示管道硬件块里——驱动只露属性,数据走blob,提交走atomic。两头都做对,4K画面不闪、不偏、不撕,量产能过屏检。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭