780M集显菊花链3台2K显示器带宽不足

现象

  • 工位单卡(780M 集显)、合盖、Type-C 菊花链 3× 2560x1440@60:第三台点不亮(前两台正常)。
  • 把第三台改成 1920x1080@60 → 能亮(最关键的旁证)。
  • eGPU(4060) 未接入,只有核显这一条链路。

根因:DP 链路带宽不够(不是驱动/线材/显示器故障)

实测链路与带宽账:

项实测值说明
链路速率4 lane @ 0x14 = HBR2总 21.6 Gbit/s(hub 只报 HBR2,无 HBR3)
DSCDSC_Sink_Support: nosink/hub 不支持 DSC,无法压缩绕过带宽
3×1440p60 @8bpc21.73 Gbit/s101% → 超了,第三台不亮
3×1440p60 @6bpc16.30 Gbit/s75% → 三台全亮(已实测)
3×1080p60 @8bpc13.37 Gbit/s62% → 能亮(所以改 1080p 就好)

带宽算式:pixel_clock × bpc × 1.25(8b/10b 编码开销)。2560x1440@60 = 241.5 MHz;1920x1080@60 = 148.5 MHz。

定位方法(可复用)

  • 看哪些口亮着:/sys/class/drm/card*-*/status 与 enabled;X 侧名用 xrandr --query(DRM 名≠X 名,例:DRM DP-10 = X DisplayPort-9)。
  • 读链路速率:/sys/kernel/debug/dri/<PCI>/DP-*/link_settings → Current: 4 0x14 ...(0x14 = HBR2 = 5.4G/lane;0x1e = HBR3 = 8.1G/lane)。
  • 读色深:同目录 max_bpc(上限,可写)与 output_bpc(sink 报的最大值,只读)。
  • 判断是否菊花链节点:is_mst_connector → no(直连/eDP) / root / branch / end(链末端的屏就是 end)。
  • DSC 能力:dp_dsc_fec_support(sink 报 no 就别指望 DSC)。
  • 内核日志:dmesg | grep -i DM_MST → DM_MST: DP12, 4-lane link detected 说明链路训练正常,瓶颈在带宽分配。

修复:把 MST 下游连接器色深上限降到 6bpc

amdgpu 的 X 属性 max bpc 被内核钉在 8..16(xrandr 改不到 6),只能写 debugfs;且该 X 属性只是 debugfs 值的只读镜像(xrandr --set 无效,无需同步)。

# 手动(需 root;写入形式必须是 0x6 且带换行)
echo 0x6 > /sys/kernel/debug/dri/0000:65:00.0/DP-10/max_bpc
cat /sys/kernel/debug/dri/0000:65:00.0/DP-10/max_bpc      # 读回应为 6
# 再让它重排一次(X 侧用 kscreen-doctor;xrandr 改布局会被 KScreen 撤销)
kscreen-doctor output.DisplayPort-9.mode.2560x1440@60

写入格式边界(实测):printf '0x6'(无换行)被内核拒(Invalid argument);printf '0x06' 也被拒;echo 0x6 / printf '0x6\n' 可以。

固化进 NixOS(重启与热插拔自动生效)

模块 /etc/nixos/modules/display-bpc.nix,开关写在 configuration.nix:

local.display.mstBpc = { enable = true; maxBpc = 6; };

两个钩子(均实测):

  • ① systemd.services.amdgpu-mst-bpc:开机时(早于 display-manager)写 debugfs。
  • ② services.udev.extraRules:DRM change(热插拔 / 链路变化)时重放。

判据用 is_mst_connector 动态挑选(不写死连接器名):只处理值不为 no 的节点(root/branch/end);直连屏与 eDP 不受影响。

验证流程(实测通过):三个连接器写回 8 → systemctl restart amdgpu-mst-bpc → 全部回到 6;服务日志 wrote 0x6 to 15 MST connector(s)(15 = 5 个 MST 连接器 × 3 个 debugfs 别名目录)。

注意:RemainAfterExit=true 的 oneshot 用 systemctl start 是空操作,重放必须 restart(曾因此误判机制失效)。

结果

  • 三台 2560x1440@60 全亮(Screen 0: 7680x1440),MST 色深上限 6。
  • 代价:色彩精度 8bpc → 6bpc(Win10 时代亦是此做法)。
  • 可选:主屏留 8bpc、另两台 6bpc(5.43×2 + 7.24 = 18.10 < 21.6 仍可);要更高色彩可再调 maxBpc,或试 force_yuv420_output(降色度采样,不推荐)。

复刻到别的机器

  • 拷 /etc/nixos/modules/ → imports = [ ./modules ]; → 打开 local.display.mstBpc → nixos-rebuild switch。
  • 模块自带脚本(writeShellScriptBin 内联),零外部依赖;面板工具与画像/快照在 /etc/nixos/scripts/,手册见 plasma-panel-cmds.txt。