Skip to content

NixOS 亮度滑块无效的修复记录 ​

问题现象 ​

系统设置中的亮度滑块可以正常显示,也可以拖动,但屏幕实际亮度没有变化。表面上看像是 GNOME 滑块事件失效,实际上滑块背后的亮度节点选错了。

本次环境如下:

  • NixOS 26.05
  • GNOME 50.4,Wayland 会话
  • NVIDIA GeForce RTX 4060 Laptop GPU
  • NVIDIA 专有驱动 595.71.05
  • Intel 核显 + NVIDIA 独显混合显卡

初步检查 ​

先查看内核暴露的背光设备:

bash
ls -l /sys/class/backlight

for d in /sys/class/backlight/*; do
    [ -d "$d" ] || continue
    echo "== $d =="
    cat "$d/type"
    cat "$d/brightness"
    cat "$d/actual_brightness"
    cat "$d/max_brightness"
    readlink -f "$d"
done

最初系统只有:

text
nvidia_wmi_ec_backlight
type=firmware
brightness=100
actual_brightness=100
max_brightness=100

这个节点可以接受写入,读回值也会变化。例如设置为 50 后,brightness 和 actual_brightness 都会变成 50。但读回成功不等于屏幕物理亮度已经变化,实际屏幕仍然保持原来的亮度。

这一步排除了几个常见原因:

  • 亮度滑块事件没有触发
  • logind 没有权限写入亮度节点
  • sysfs 文件完全不可写

真正的问题是 WMI 节点虽然能保存数值,却没有控制当前内屏的实际背光。

Ubuntu 方案的适用性 ​

参考的 Ubuntu 方案主要包括 acpi_backlight=vendor、NVIDIA 的 EnableBrightnessControl=1,以及直接操作 /sys/class/backlight 的方法:

Ubuntu NVIDIA 亮度问题解决方案

这些方法不能直接全部照搬到当前环境:

acpi_backlight=vendor ​

测试后 /sys/class/backlight 变为空,GNOME 亮度滑块也随之消失。因此这个参数不适合当前硬件,随后撤销。

EnableBrightnessControl=1 ​

在 NixOS 中可以通过 NVIDIA 模块参数配置:

nix
hardware.nvidia.moduleParams = {
  nvidia.NVreg_RegistryDwords = "EnableBrightnessControl=1";
};

但当前使用的是 NVIDIA 595 驱动和 GNOME Wayland,会话并不是 Ubuntu 文章中的 Xorg 场景。加入该参数后,内核仍然提示没有 NVIDIA 原生背光控制,屏幕亮度没有恢复。

因此,问题不在于简单地给滑块增加权限,而在于内核选择了错误的背光控制路径。

找到真正的背光节点 ​

最终使用的内核参数是:

nix
boot.kernelParams = [
  "acpi_backlight=native"
];

重新构建并重启:

bash
sudo nixos-rebuild switch
sudo systemctl reboot

重启后出现了新的节点:

text
nvidia_0
type=raw
brightness=48
actual_brightness=48
max_brightness=100

这里的 nvidia_0 是 NVIDIA 原生背光节点,而原来的 nvidia_wmi_ec_backlight 是 WMI 固件节点。通过 logind 直接测试原生节点:

bash
sudo busctl call \
  org.freedesktop.login1 \
  /org/freedesktop/login1/session/_32 \
  org.freedesktop.login1.Session \
  SetBrightness ssu backlight nvidia_0 20

测试结果为:

text
nvidia_0 brightness=20
nvidia_0 actual_brightness=20

这证明原生节点能够正确接收系统亮度服务的调用。

为什么还要移除 WMI 强制参数 ​

第一次测试 acpi_backlight=native 时,为了保留回退路径,额外加入了:

text
nvidia_wmi_ec_backlight.force=1

这样系统同时出现 nvidia_0 和 nvidia_wmi_ec_backlight 两个节点。两个节点同时存在时,桌面环境仍可能选到 WMI 节点,导致滑块看起来在工作,但屏幕亮度不变。

因此最终配置只保留:

nix
boot.kernelParams = [
  "acpi_backlight=native"
];

移除 WMI 强制加载参数后,GNOME 亮度滑块使用 NVIDIA 原生控制器,拖动亮度已经可以正常生效。

最终验证 ​

可以使用下面的命令确认系统当前使用的节点:

bash
ls -l /sys/class/backlight

for d in /sys/class/backlight/*; do
    [ -d "$d" ] || continue
    printf '%s: ' "$(basename "$d")"
    printf 'type='; cat "$d/type"
    printf 'brightness='; cat "$d/brightness"
    printf 'actual='; cat "$d/actual_brightness"
done

重点是确认亮度滑块写入的是 nvidia_0,而不是只检查某个文件的数值是否变化。对于这类问题,“写入成功并读回”只能证明控制节点接受了数据,最终还需要观察屏幕物理亮度是否变化。

结论 ​

本次故障的根因是 NVIDIA 混合显卡环境下,系统默认使用了无效的 WMI 背光节点。最终修复方法是:

  1. 不使用会导致背光设备消失的 acpi_backlight=vendor。
  2. 使用 acpi_backlight=native 让内核创建 NVIDIA 原生节点 nvidia_0。
  3. 不强制加载 nvidia_wmi_ec_backlight,避免桌面环境选错控制器。
  4. 重建 NixOS 配置并重启。

这个修复针对当前 NVIDIA RTX 4060 Laptop + GNOME Wayland 环境。其他电脑如果显卡型号、驱动版本或内核不同,应该先检查 /sys/class/backlight,再决定实际使用哪个节点。

Last updated:

Build fast, ship useful things.