4. HDMI CEC¶
4.1. 主线中支持的硬件¶
HDMI 发射器
Exynos4
Exynos5
STIH4xx HDMI CEC
V4L2 adv7511 (相同的硬件,但与 drm adv7511 驱动程序不同)
stm32
Allwinner A10 (sun4i)
Raspberry Pi
dw-hdmi (Synopsis IP)
amlogic (meson ao-cec 和 ao-cec-g12a)
drm adv7511/adv7533
omap4
tegra
rk3288, rk3399
tda998x
i915、nouveau 和 amdgpu 上的 DisplayPort CEC-Tunneling-over-AUX
ChromeOS EC CEC
SECO 板 (UDOO x86) 的 CEC。
Chrontel CH7322
HDMI 接收器
adv7604/11/12
adv7842
tc358743
USB 加密狗 (有关如何使用这些加密狗的更多信息,请参见下文)
Pulse-Eight:pulse8-cec 驱动程序实现以下模块选项:
persistent_config
:默认情况下此选项处于关闭状态,但设置为 1 时,驱动程序会将当前设置存储到设备的内部 eeprom,并在下次设备连接到 USB 端口时恢复它。RainShadow Tech. 注意:此驱动程序不支持 Pulse-Eight 驱动程序的 persistent_config 模块选项。硬件支持它,但我没有计划添加此功能。但我接受补丁 :-)
Extron DA HD 4K PLUS HDMI 分配放大器。有关更多信息,请参见 Extron DA HD 4K PLUS CEC 适配器驱动程序。
其他
vivid:模拟 CEC 接收器和 CEC 发射器。可用于在没有实际 CEC 硬件的情况下测试 CEC 应用程序。
cec-gpio。如果 CEC 引脚连接到 GPIO 引脚,则可以通过此驱动程序控制 CEC 线。这也支持错误注入。
cec-gpio 和 Allwinner A10 (或任何其他使用 CEC 引脚框架直接驱动 CEC 引脚的驱动程序):CEC 引脚框架使用高分辨率计时器。这些计时器受 NTP 守护进程的影响,NTP 守护进程会加速或减慢时钟以与官方时间同步。chronyd 服务器默认情况下会将时钟增加或减少 1/12。这将导致 CEC 时序超出规格。要解决此问题,请在 chronyd.conf 中添加 “maxslewrate 40000” 行。这将时钟频率变化限制为 1/25,从而使 CEC 时序保持在规格范围内。
4.2. 实用工具¶
实用工具在此处可用:https://git.linuxtv.org/v4l-utils.git
utils/cec-ctl
:控制 CEC 设备
utils/cec-compliance
:测试远程 CEC 设备的合规性
utils/cec-follower
:模拟 CEC 从设备
请注意,cec-ctl
支持某些酒店显示器中使用的 CEC 酒店配置文件。请参阅 http://www.htng.org。
请注意,libcec 库 (https://github.com/Pulse-Eight/libcec) 支持 linux CEC 框架。
如果要获取 CEC 规范,请查看 HDMI 维基百科页面的参考资料:https://en.wikipedia.org/wiki/HDMI。CEC 是 HDMI 规范的一部分。HDMI 1.3 是免费提供的 (与 CEC 相关的 HDMI 1.4 非常相似),应该足以满足大多数需求。
4.3. 具有工作 CEC 的 DisplayPort 到 HDMI 适配器¶
背景:大多数适配器不支持 CEC 隧道功能,而在支持该功能的适配器中,许多实际上没有连接 CEC 引脚。不幸的是,这意味着虽然创建了 CEC 设备,但它实际上是孤立的,永远无法看到其他 CEC 设备。
这是已知具有 CEC 隧道并且正确连接 CEC 引脚的工作适配器列表。如果您发现有效但未在此列表中的适配器,请给我留言。
要测试:将您的 DP 到 HDMI 适配器连接到支持 CEC 的设备 (通常是电视),然后运行
cec-ctl --playback # Configure the PC as a CEC Playback device
cec-ctl -S # Show the CEC topology
cec-ctl -S
命令应至少显示两个 CEC 设备,我们自己和您连接的 CEC 设备 (即通常是电视)。
一般说明:我只看到 Parade PS175、PS176 和 PS186 芯片组以及 MegaChips 2900 才能正常工作。虽然 MegaChips 28x0 声称支持 CEC,但我从未见过它工作。
4.3.1. USB-C 到 HDMI¶
三星多端口适配器 EE-PW700:https://www.samsung.com/ie/support/model/EE-PW700BBEGWW/
Kramer ADC-U31C/HF:https://www.kramerav.com/product/ADC-U31C/HF
Club3D CAC-2504:https://www.club-3d.com/en/detail/2449/usb_3.1_type_c_to_hdmi_2.0_uhd_4k_60hz_active_adapter/
4.3.2. DisplayPort 到 HDMI¶
Club3D CAC-1080:https://www.club-3d.com/en/detail/2442/displayport_1.4_to_hdmi_2.0b_hdr/
CableCreation (SKU: CD0712):https://www.cablecreation.com/products/active-displayport-to-hdmi-adapter-4k-hdr
HP DisplayPort 到 HDMI True 4k 适配器 (P/N 2JA63AA):https://www.hp.com/us-en/shop/pdp/hp-displayport-to-hdmi-true-4k-adapter
4.3.3. Mini-DisplayPort 到 HDMI¶
Club3D CAC-1180:https://www.club-3d.com/en/detail/2443/mini_displayport_1.4_to_hdmi_2.0b_hdr/
请注意,被动适配器永远无法工作,您需要一个主动适配器。
此列表中的 Club3D 适配器均基于 MegaChips 2900 芯片。其他 Club3D 适配器基于 PS176 芯片,并且没有连接 CEC 引脚,因此只有上述三个 Club3D 适配器已知可以正常工作。
我怀疑一般而言,基于 MegaChips 2900 的设计很可能可以工作,而 PS176 则更不稳定(大多数情况下都不能工作)。PS186 很可能连接了 CEC 引脚,看起来他们更改了该芯片组的参考设计。
4.4. USB CEC 加密狗¶
这些加密狗显示为 /dev/ttyACMX
设备,需要 inputattach
实用程序来创建 /dev/cecX
设备。Pulse-Eight 的支持已添加到 inputattach
1.6.0 中。Rainshadow Tech 的支持已添加到 inputattach
1.6.1 中。
您还需要 udev 规则来自动启动 systemd 服务
SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="2548", ATTRS{idProduct}=="1002", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="pulse8-cec-inputattach@%k.service"
SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="2548", ATTRS{idProduct}=="1001", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="pulse8-cec-inputattach@%k.service"
SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="ff59", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rainshadow-cec-inputattach@%k.service"
以及这些 systemd 服务
对于 Pulse-Eight,创建 /lib/systemd/system/[email protected]
[Unit]
Description=inputattach for pulse8-cec device on %I
[Service]
Type=simple
ExecStart=/usr/bin/inputattach --pulse8-cec /dev/%I
对于 RainShadow Tech,创建 /lib/systemd/system/[email protected]
[Unit]
Description=inputattach for rainshadow-cec device on %I
[Service]
Type=simple
ExecStart=/usr/bin/inputattach --rainshadow-cec /dev/%I
为了获得正确的挂起/恢复支持,创建:/lib/systemd/system/restart-cec-inputattach.service
[Unit]
Description=restart inputattach for cec devices
After=suspend.target
[Service]
Type=forking
ExecStart=/bin/bash -c 'for d in /dev/serial/by-id/usb-Pulse-Eight*; do /usr/bin/inputattach --daemon --pulse8-cec $d; done; for d in /dev/serial/by-id/usb-RainShadow_Tech*; do /usr/bin/inputattach --daemon --rainshadow-cec $d; done'
[Install]
WantedBy=suspend.target
并运行 systemctl enable restart-cec-inputattach
。
为了在 EDID 更改时自动设置 CEC 设备的物理地址,您可以使用带有 -E
选项的 cec-ctl
cec-ctl -E /sys/class/drm/card0-DP-1/edid
这假设加密狗连接到 card0-DP-1 输出(xrandr
会告诉您使用哪个输出),它将轮询 EDID 的更改,并在发生更改时更新物理地址。
要自动运行此命令,您可以使用 cron。使用 crontab -e
编辑 crontab 并添加此行
@reboot /usr/local/bin/cec-ctl -E /sys/class/drm/card0-DP-1/edid
这仅适用于在 /sys/class/drm
中公开 EDID 的显示驱动程序,例如 i915 驱动程序。
4.5. 无 HPD 的 CEC¶
某些显示器在待机模式下没有 HDMI 热插拔检测信号,但仍然启用 CEC,因此连接的设备可以发送一个 <Image View On> CEC 消息,以便唤醒此类显示器。不幸的是,并非所有 CEC 适配器都支持此功能。例如,Odroid-U3 SBC 有一个电平转换器,当 HPD 信号较低时,该电平转换器会关闭电源,从而阻止 CEC 引脚。即使 SoC 可以在没有 HPD 的情况下使用 CEC,电平转换器也会阻止其正常工作。
有一个 CEC 功能标志可以表示这一点:CEC_CAP_NEEDS_HPD
。如果设置了此标志,则硬件无法唤醒具有此行为的显示器。
针对 CEC 应用程序实现者的注意事项:<Image View On> 消息必须是您发送的第一条消息,不要在此之前发送任何其他消息。某些非常糟糕但不幸并不罕见的 CEC 实现如果收到此消息以外的任何其他消息,就会非常困惑,并且不会唤醒。
在编写驱动程序时,测试这一点可能很棘手。有两种方法可以做到这一点
获取一个 Pulse-Eight USB CEC 加密狗,将 HDMI 电缆从您的设备连接到 Pulse-Eight,但不要将 Pulse-Eight 连接到显示器。
现在配置 Pulse-Eight 加密狗
cec-ctl -p0.0.0.0 --tv
并开始监控
sudo cec-ctl -M
在您要测试的设备上运行
cec-ctl --playback
它应该报告物理地址为 f.f.f.f。现在运行此命令
cec-ctl -t0 --image-view-on
Pulse-Eight 应该看到 <Image View On> 消息。如果看不到,则某些东西(硬件和/或软件)正在阻止 CEC 消息发出。
为了确保您的接线正确,只需将 Pulse-Eight 连接到支持 CEC 的显示器并在您的设备上运行相同的命令:现在有一个 HPD,因此您应该看到命令到达 Pulse-Eight。
如果您有另一个支持无 HPD 的 CEC 的 Linux 设备,那么您可以将您的设备连接到该设备。是的,您可以将两个 HDMI 输出连接在一起。您不会有 HPD(这是我们为此测试所需要的),但第二个设备可以监控 CEC 引脚。
否则,请使用与 1 中相同的命令。
如果当没有 HPD 时 CEC 消息没有传递过来,那么您需要找出原因。通常,要么是硬件限制,要么是软件在 HPD 变低时关闭 CEC 内核的电源。第一个当然无法纠正,第二个可能需要更改驱动程序。
4.6. 微控制器和 CEC¶
我们已经看到一些显示器中的 CEC 实现使用微控制器来采样总线。这不一定是个问题,但某些实现存在时序问题。除非您可以连接低级 CEC 调试器(请参阅下一节),否则很难发现这一点。
您会看到 CEC 发射器将 CEC 线保持高电平或低电平的时间长于允许的时间的情况。对于定向消息,这不是问题,因为如果发生这种情况,该消息将不会被确认,并且会被重新传输。对于广播消息,不存在这种机制。
尚不清楚如何处理这个问题。可能明智的做法是将某些广播消息发送两次,以减少它们丢失的机会。特别是 <Standby> 和 <Active Source> 是其候选者。
4.7. 制作 CEC 调试器¶
通过使用 Raspberry Pi 4B 和一些廉价的组件,您可以制作自己的低级 CEC 调试器。
关键组件是以下 HDMI 母对母直通连接器之一(全焊接 1 型)
视频质量是可变的,当然不足以直通 4kp60 (594 MHz) 视频。您可能能够支持 4kp30,但更有可能您将被限制为 1080p60 (148.5 MHz)。但对于 CEC 测试,这没问题。
您需要一个面包板和一些面包板导线
如果您还想监控 HPD 和/或 5V 线,那么您需要以下 5V 到 3.3V 电平转换器之一
https://www.adafruit.com/product/757
(这只是我获得这些组件的地方,还有许多其他地方可以获得类似的东西)。
当然,HDMI 连接器的接地引脚需要连接到 Raspberry Pi 的接地引脚。
HDMI 连接器的 CEC 引脚需要连接到以下引脚:GPIO 6 和 GPIO 7。HDMI 连接器的可选 HPD 引脚应通过电平转换器连接到以下引脚:GPIO 23 和 GPIO 12。HDMI 连接器的可选 5V 引脚应通过电平转换器连接到以下引脚:GPIO 25 和 GPIO 22。监控 HPD 和 5V 线不是必需的,但它很有帮助。
在 arch/arm/boot/dts/bcm2711-rpi-4-b.dts
中的此设备树添加将正确连接 cec-gpio 驱动程序
cec@6 {
compatible = "cec-gpio";
cec-gpios = <&gpio 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
hpd-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
v5-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
};
cec@7 {
compatible = "cec-gpio";
cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
hpd-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
};
如果您没有连接 HPD 和/或 5V 线,那么只需删除这些行即可。
此 dts 更改将启用两个 cec GPIO 设备:我通常使用一个来发送/接收 CEC 命令,另一个用于监控。如果您使用未配置的 CEC 适配器进行监控,那么它将使用 GPIO 中断,这使得监控非常准确。
如果您只想监控流量,那么一个实例就足够了。最少的配置是一个 HDMI 母对母直通连接器和两个母对母面包板导线:一个用于将 HDMI 接地引脚连接到 Raspberry Pi 上的接地引脚,另一个用于将 HDMI CEC 引脚连接到 Raspberry Pi 上的 GPIO 6。
有关如何使用错误注入的文档在此处:CEC 引脚框架错误注入。
cec-ctl --monitor-pin
将进行低级 CEC 总线嗅探和分析。您还可以使用 --store-pin
将 CEC 流量存储到文件中,并稍后使用 --analyze-pin
进行分析。
您还可以通过使用 cec-ctl --tv -p0.0.0.0
或 cec-ctl --playback -p1.0.0.0
配置它来将其用作功能完善的 CEC 设备。
4.8. Extron DA HD 4K PLUS CEC 适配器驱动程序¶
此驱动程序适用于 Extron DA HD 4K PLUS 系列 HDMI 分配放大器:https://www.extron.com/product/dahd4kplusseries
支持 2、4 和 6 端口型号。
需要固件版本 1.02.0001 或更高版本。
请注意,旧的 Extron 硬件版本在 CEC 电压方面存在问题,这可能意味着 CEC 将无法工作。这在硬件版本 E34814 及更高版本中得到了修复。
CEC 支持有两种模式:第一种是手动模式,用户空间必须手动控制 HDMI 输入和所有 HDMI 输出的 CEC。虽然这提供了完全控制,但也比较复杂。
第二种模式是自动模式,如果设置了模块选项 vendor_id
,则选择此模式。在这种情况下,驱动程序控制 CEC,并且在输入中接收到的 CEC 消息将分发到输出。仍然可以使用 /dev/cecX 设备直接与连接的设备通信,但驱动程序负责配置所有内容并处理诸如热插拔检测更改之类的事情。
驱动程序还负责 EDID:创建 /dev/videoX 设备以读取 EDID 并(对于 HDMI 输入端口)设置 EDID。
默认情况下,用户空间负责根据连接显示器的 EDID 设置 HDMI 输入的 EDID。但是,如果设置了 manufacturer_name
模块选项,则驱动程序将根据连接显示器支持的分辨率来设置 HDMI 输入的 EDID。目前,驱动程序仅支持 1080p60 和 4kp60 分辨率:如果所有连接的显示器都支持 4kp60,则它将在 HDMI 输入上通告 4kp60;否则,它将回退到仅报告 1080p60 的 EDID。
Extron 的状态报告在 /sys/kernel/debug/cec/cecX/status
中。
extron-da-hd-4k-plus 驱动程序实现了以下模块选项
4.8.1. debug
¶
如果设置为 1,则会显示所有串行端口流量。
4.8.2. vendor_id
¶
要报告给连接的显示器的 CEC 供应商 ID。
如果设置了此选项,则驱动程序将负责将输入端接收到的 CEC 消息分发到 HDMI 输出。这针对以下 CEC 消息进行:
<待机>
<图像显示开启> 和 <文本显示开启>
<请求设备电源状态>
<设置系统音频模式>
<请求当前延迟>
如果未设置,则用户空间负责此操作,并且它必须手动配置 HDMI 输入和 HDMI 输出的 CEC 设备。
4.8.3. manufacturer_name
¶
一个三字符制造商名称,用于 HDMI 输入的 EDID 中。如果未设置,则用户空间负责配置 EDID。如果设置,则驱动程序将根据连接显示器支持的分辨率自动更新 EDID,并且不再可能手动设置 HDMI 输入的 EDID。
4.8.4. hpd_never_low
¶
如果设置,则 HDMI 输入的热插拔检测引脚将始终为高电平,即使未连接任何 HDMI 输出。如果未设置(默认设置),则如果检测到的所有 HDMI 输出的热插拔检测引脚也为低电平,则 HDMI 输入的热插拔检测引脚将变为低电平。
此选项可以动态更改。