最近给笔记本接上 4K 显示器以后,在 KDE Plasma Wayland 下移动鼠标总觉得一顿一顿的。手上这只无线鼠标标称 8K 回报率,所以我第一反应是回报率没跑起来,于是先从输入设备和 USB HID 链路开始查。结果绕了一圈才发现,鼠标本身没什么问题,真正的原因藏在显示器的 TypeC 的连接里。
这里把排查过程整理一下,也算给自己留个记录。
环境
| 项目 | 配置 |
|---|---|
| 系统 | Kalpa Desktop |
| 内核 | Linux 7.2.6 |
| 桌面 | KDE Plasma Wayland |
| 笔记本 | ThinkPad X1 Carbon Gen 8 |
| CPU / GPU | Intel Core i7-10510U |
| 显卡驱动 | i915 |
| 显示器 | Philips 27E1N8900,3840x2160 |
| 连接方式 | TypeC 直连显示器 |
先怀疑鼠标回报率
通过 AI 相互排查,从 /proc/bus/input/devices 可以找到鼠标的主输入节点:
N: Name="Compx Wireless mouse 8k NANO dongle-L"
H: Handlers=mouse4 event10
I: Bus=0003 Vendor=373b Product=11fe Version=0111USB 拓扑显示接收器工作在 High-Speed USB 链路上:
Bus 001 Device 008: ID 373b:11fe Compx Wireless mouse 8k NANO dongle-L
Driver=usbhid, 480M再看 USB HID 的端点描述符:
bEndpointAddress 0x81 EP 1 IN
wMaxPacketSize 0x0007 1x 7 bytes
bInterval 1sysfs 里给出的实际轮询间隔是:
/sys/bus/usb/devices/1-2.3/1-2.3:1.0/ep_81 interval=125us换算成理论轮询频率:
$$ f = \frac{1}{125\ \mu s} = 8000\ Hz $$
另外顺手确认了这两项:
power/control=on
usbhid mousepoll=0到这里其实基本可以排除几个常见的怀疑对象:
- USB 主机端没有把鼠标限制在低回报率;
- 接收器端点具备 8000 Hz 的理论轮询能力;
- USB 自动挂起没有让接收器周期性休眠;
- 内核也没有通过
usbhid.mousepoll强制覆盖设备回报率。
真正的问题:屏幕只有 30 Hz
既然鼠标这边看不出毛病,就回头看了一眼 KDE 的输出配置:
Output: DP-2
Resolution: 3840x2160
Refresh rate: 29.98 Hz
Scale: 2刷新率只有 29.98 Hz。大约 30 Hz 下每一帧大约持续:
$$ t = \frac{1}{29.98} \approx 33.4\ ms $$
也就是说,鼠标哪怕按 1000 Hz 甚至 8000 Hz 上报,屏幕每秒也只能画出大约 30 次位置变化,看起来自然是一跳一跳的。
所以我改变了排查的方向,应该是屏幕刷新率的问题了。当时 DRM/KScreen 能提供的高分辨率模式只有这几个:
[email protected]
[email protected]
[email protected]显示器和显卡其实都支持 4K60
先确认 GPU 和驱动:
Intel Corporation CometLake-U GT2 [UHD Graphics] [8086:9b41]
Kernel driver in use: i915再解析显示器 EDID 里的首选详细时序:
DTD: 3840x2160
pixel_clock=533.25 MHz
refresh=59.997 Hz由此可以确认:
- 显示器原生支持 3840x2160@60 Hz;
- Intel GPU 和 i915 都支持这个输出;
- 60 Hz 并不是 KDE 主动隐藏的,而是内核根据当前链路带宽,把传不动的模式过滤掉了。
问题于是变成了:链路带宽为什么不够?
中间的一次误判
机器上当时还接着一个 Belkin USB-C Multimedia Hub(USB ID 050d:092b/092c)。这款产品的规格本来就只支持 4K30,所以我一度以为是内核误判了视频信号走的是这个 Hub。
后来让 AI 跑了下排查,发现 Type-C partner、USB 根设备和 DRM 连接器逐一对应起来,其实内核已经弄清楚了情况:
port0 -> VIA Labs USB 2.0/3.0 Hub -> 显示器直连
port1 -> Belkin USB-C Multimedia Hub
DP-1 -> port0 的显示器视频链路Belkin Hub 虽然也插在电脑上,但并不在这台显示器的视频路径里。
根因:USB 3.x 占掉了两条 lane
所以问题就又回到了显示器上,这台显示器是通过一根 TypeC 一线通是同时提供三样东西的:
- DisplayPort Alt Mode 视频;
- 显示器内置 USB Hub 的数据传输;
- USB Power Delivery 供电。
排查时,显示器内置的 VIA Labs USB Hub 正以 USB 3.x 速率工作:
2109:0817 USB3.0 Hub
speed=5000在常见的 USB-C DP Alt Mode 配置下,USB 3.x 会占用两条高速 lane,留给 DisplayPort 的就只剩两条。Comet Lake 平台跑 HBR2 时,两条 lane 的有效带宽是:
$$ DP\ HBR2\ x2 = 5.4 \times 2 \times 0.8 = 8.64\ Gbit/s $$
而这台显示器 4K60 RGB 8-bit 的有效像素数据大约是:
$$ 533.25\ MHz \times 24\ bit \approx 12.80\ Gbit/s $$
两条 HBR2 lane 显然扛不住。如果四条 lane 都给 DisplayPort,有效带宽则是:
$$ DP\ HBR2\ x4 = 5.4 \times 4 \times 0.8 = 17.28\ Gbit/s $$
足够跑 4K60。所以根因很清楚:显示器内置的 USB Hub 跑在 USB 3.x 模式,DisplayPort 只分到两条 lane,链路最多只能撑到 4K30。
解决办法
那么我就尝试在显示器 OSD 里把 USB 数据模式切换到 USB 2.0,或者叫「高分辨率优先」之类的选项,然后重新插拔一次 TypeC 线。这样 USB 2.0 数据会改走独立的低速线对,四条高速 lane 都可以分配给 DisplayPort。代价是显示器内置 USB Hub 的速率从 5 Gbit/s 降到 480 Mbit/s(这个问题对于链接鼠标键盘这类的设备来说,问题不大)。
果然,飞利浦的这款 OLED 显示器有对应的选项,于是我在 OSD 选线中选择了视频分辨率优先,然后重新插拔显示器链接的 TypeC 一线通。
切换后的验证
切换完成后,DRM 状态如下:
DP-1 status=connected
DP-1 enabled=enabled/sys/class/drm/card1-DP-1/modes 里出现了两个 3840x2160 条目,说明 4K60 模式已经重新回到内核的模式列表里。
KWin 的输出配置记录为:
{
"width": 3840,
"height": 2160,
"refreshRate": 59997,
"scale": 2,
"highDynamicRange": false,
"wideColorGamut": false
}实际刷新率约为 59.997 Hz。
与此同时,原来的 USB3 节点消失了,只剩下显示器的 USB 2.0 Hub(而我实际上也没有把鼠标和键盘都链接到这个 Hub 上):
idVendor=2109
idProduct=2817
product=USB2.0 Hub
speed=480配置确实按预期生效了:USB Hub 降到 USB 2.0,DisplayPort 拿回四条高速 lane,4K60 正常工作。之前因为 30 Hz 带来的明显的鼠标卡顿感,也就跟着消失了。
顺手做的核显优化
那么问题解决以后,我又顺便看了一下 Intel 核显跑 4K60 的整体状态。AI Agent 帮我总结了下,目前的环境已经有不少有利条件:
- 使用 KDE Plasma Wayland,没有额外的 X11 合成路径;
- 输出为 [email protected] Hz;
- 2 倍整数缩放,省掉了分数缩放带来的额外开销;
- HDR 和 Wide Color Gamut 都是关闭的;
- 已安装 Mesa 和
intel-media-driver,图形和 VA-API 视频硬件加速都有着落; - Intel P-state 正常启用;
- iGPU 可以在
300–1150 MHz之间动态调频,检查时跑到了883 MHz; - 接着交流电源,CPU energy-performance preference 为
balance_performance。
内核参数方面,在十代 Comet Lake 上强制打开 GuC、PSR 或 DC 并不会提高物理刷新率,反而可能把内核状态搞乱,带来闪屏、冻结或者休眠恢复后黑屏之类的问题。FBC 也还是交给每个平台的默认策略比较稳妥。
倒是考虑为了减少后台内存规整带来的桌面帧延迟尖峰,我在工作站的 sysctl 配置里加了一行:
vm.compaction_proactiveness = 0这台机器已经把 Transparent Huge Pages 限制为 madvise,主动内存规整对普通桌面程序的收益本来就有限,关掉以后更偏向交互延迟的稳定。
结论
回头来看,这次的问题并不是鼠标 USB 回报率太低,而是显示链路只跑在 30 Hz:
显示器 USB Hub 使用 USB 3.x
↓
USB-C 只给 DisplayPort 分配两条 HBR2 lane
↓
4K60 带宽不足,内核只提供 4K30
↓
屏幕每 33.4 ms 才更新一次,鼠标视觉上明显卡顿把显示器 USB Hub 切换到 USB 2.0 以后,DisplayPort 拿到四条高速 lane,4K60 模式恢复,问题也就解决了。所以显示器的配置问题还是需要各个系统环境的具体配置,同时我也好奇为啥 Windows 和 macOS 下原有配置还是能跑 60Hz 的视频输出,可能是 Linux 内核对于这块更加严格或者谨慎一些吧(谁知道呢)。