👁 482

硬件信息

项目 详情
系统 Arch Linux, 内核 7.0.10-arch1-1
显卡 Intel CometLake-U GT2 (UHD Graphics), i915 驱动
显示器 AOC U27G3X (4K@60Hz)
连接方式 Type-C DP Alt Mode → LSPCON (DP-1)
启动方式 UKI + GRUB 双路径

问题现象

  1. 开机灰屏:按电源键直接进系统,屏幕灰屏无显示(键盘大小写灯有反应);必须手动按 BIOS 快捷键选 GRUB 引导才能正常显示
  2. 休眠/待机很难唤醒:唤醒后黑屏或长时间无法恢复显示

根因分析

1. UKI 未重建 — 开机灰屏的主因

系统使用 UKI 启动(/efi/EFI/Linux/arch-linux.efi),内核参数打包在 UKI 内部,不会动态读取配置文件。

GRUB 的 15_uki 脚本会自动检测并加载 UKI。之前在 /etc/default/grub 里加了 i915 参数,但 UKI 从未重建(文件时间停留在5月28日),所以:

  • 走 UKI 路径(GRUB 自动加载 / systemd-boot)→ 旧 UKI 无 i915 参数 → 灰屏
  • 手动选 GRUB 的 10_linux 条目 → 读 /etc/default/grub 的参数 → 正常

2. LSPCON 初始化失败

dmesg 报错:

i915 0000:00:02.0: [drm] *ERROR* Failed to probe lspcon

LSPCON 是 DP 转 HDMI 2.0 的协议转换芯片,睡眠唤醒后没有正确重新初始化。

3. 显示电源域关闭后不恢复

CometLake 平台的 i915 驱动在睡眠时关闭显示电源域,唤醒后无法正确重新上电。

4. systemd-boot 入口损坏

/efi/loader/entries/arch.conf 引用了不存在的 /vmlinuz-linux 和 /initramfs-linux.img(Type #1 入口),导致 systemd-boot 路径完全不可用。

修复步骤

修复 1:重建 UKI(核心修复)

文件: /etc/kernel/cmdline

root=PARTUUID=51587848-6d64-45cd-af69-841a0ae6e30d rw rootfstype=ext4 i915.enable_dc=0 i915.enable_psr=0 i915.enable_dpcd_backlight=1 i915.disable_power_well=0 mem_sleep_default=s2idle

注意:已移除废弃的 i915.modeset=1(内核提示 deprecated,默认即为1)

mount -o remount,fmask=0022,dmask=0022 /efi
mkinitcpio -P

验证:

strings /efi/EFI/Linux/arch-linux.efi | grep 'i915.enable_dc=0'

修复 2:修正 mkinitcpio preset

文件: /etc/mkinitcpio.d/linux.preset

UKI 路径从相对路径改为绝对路径:

default_uki="/efi/EFI/Linux/arch-linux.efi"

修复 3:修复 systemd-boot 入口

文件: /efi/loader/entries/arch.conf

从损坏的 Type #1 改为引导 UKI:

title Arch-Sun
efi /EFI/Linux/arch-linux.efi

修复 4:同步 GRUB 配置

文件: /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet i915.enable_dc=0 i915.enable_psr=0 i915.enable_dpcd_backlight=1 i915.disable_power_well=0 mem_sleep_default=s2idle"

重新生成:

grub-mkconfig -o /efi/grub/grub.cfg

修复 5:创建唤醒恢复服务

文件: /etc/systemd/system/i915-resume-fix.service

[Unit]
Description=Reinitialize i915 display after resume
After=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target

[Service]
Type=oneshot
ExecStartPre=/usr/bin/sleep 2
ExecStart=/usr/bin/bash -c 'for d in /sys/class/drm/card*-DP-*; do if [ "$(cat $d/status 2>/dev/null)" = "connected" ]; then echo 0 > $d/dpms 2>/dev/null; echo 1 > $d/dpms 2>/dev/null; fi; done'

[Install]
WantedBy=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target
systemctl enable i915-resume-fix.service

修复 6:双系统时间同步

Linux RTC 从 UTC 改为本地时间,和 Windows 一致:

timedatectl set-local-rtc 1
timedatectl set-ntp true
hwclock --systohc --localtime

参数说明

参数 作用
i915.enable_dc=0 禁用 DC 省电状态,唤醒后显示管线不恢复的主因
i915.enable_psr=0 禁用 PSR 面板自刷新,CometLake 上不稳定
i915.enable_dpcd_backlight=1 通过 DPCD 控制背光(DP 转接需要)
i915.disable_power_well=0 禁止关闭显示电源域,唤醒后电源域不重新上电也会黑屏
mem_sleep_default=s2idle CometLake 对 S3 (deep) 支持差,改用 s2idle

引导路径总览

开机
├─ BIOS BootOrder 首位: GRUB (0007)
│   ├─ 10_linux 条目 → 读 /etc/default/grub 参数 → 正常
│   └─ 15_uki 自动加载 → arch-linux.efi (UKI) → 已修复,参数完整
├─ systemd-boot (手动选择时)
│   └─ arch.conf → arch-linux.efi (UKI) → 已修复
└─ /EFI/BOOT/BOOTX64.EFI → GRUB → 同上

重启后验证

# 1. 确认参数已生效(不应有 i915.modeset=1)
cat /proc/cmdline

# 2. 确认 i915 参数值
cat /sys/module/i915/parameters/enable_dc          # 应为 0
cat /sys/module/i915/parameters/enable_psr          # 应为 0
cat /sys/module/i915/parameters/disable_power_well  # 应为 0

# 3. 确认睡眠模式
cat /sys/power/mem_sleep  # 应为 [s2idle] deep

# 4. 确认时间同步
timedatectl | grep "RTC in local"  # 应为 yes

# 5. 不按快捷键直接开机,验证不再灰屏

# 6. 测试睡眠唤醒
systemctl suspend

如果唤醒仍然黑屏

  1. 切换 TTY: Ctrl+Alt+F2 再 Ctrl+Alt+F1 切回
  2. 重启显示管理器: systemctl restart display-manager
  3. 强制重新检测显示:
    for d in /sys/class/drm/card*-DP-*; do
      echo detect > $d/status 2>/dev/null
    done
  4. 如果 s2idle 也不行,尝试加 i915.enable_guc=2:
    # /etc/kernel/cmdline 中加入 i915.enable_guc=2
    # 然后重新 mkinitcpio -P

注意事项

  • 每次修改 /etc/kernel/cmdline 后都必须运行 mkinitcpio -P 重新生成 UKI,否则参数不会生效
  • 修改 /etc/default/grub 后需运行 grub-mkconfig -o /efi/grub/grub.cfg
  • disable_power_well=0 会略微增加功耗,但对唤醒稳定性至关重要
  • mem_sleep_default=s2idle 比 deep (S3) 省电效果差,但 CometLake 上更稳定
  • 如果以后内核更新后问题复现,先检查 UKI 是否被重建、cmdline 是否被覆盖