背光
屏幕亮度可能难以控制。在某些机器上,物理硬件开关缺失,软件解决方案可能无法很好地工作。但是,通常可以为给定的硬件找到一种有效的方法。本文旨在总结所有可能的调整背光的方法。
有很多方法可以控制显示器、笔记本电脑或集成面板(如 iMac)的亮度。根据 这些 讨论[死链 2024-10-12 ⓘ] 和这篇 wiki 页面,控制方法可以分为以下几类
- 亮度由供应商指定的快捷键控制,操作系统没有接口来调整亮度。
- 亮度由 ACPI、图形驱动或平台驱动控制。在这种情况下,背光控制通过
/sys/class/backlight
暴露给用户,用户空间 背光工具 可以使用它。 - 亮度通过 setpci 写入显卡寄存器来控制。
硬件接口
ACPI
屏幕背光的亮度通过设置背光 LED 或阴极的功率级别来调整。功率级别通常可以使用视频的 ACPI 内核模块来控制。通过 sysfs(5) 目录 /sys/class/backlight/
提供了此模块的接口。
目录的名称取决于显卡型号。
$ ls /sys/class/backlight/
acpi_video0
在这种情况下,背光由 ATI 显卡管理。如果是 Intel 显卡,则目录名为 intel_backlight
。在以下示例中,使用 acpi_video0
。如果您使用 Intel 显卡,只需在示例中将 acpi_video0
替换为 intel_backlight
。
该目录包含以下文件和子目录
$ ls /sys/class/backlight/acpi_video0/
actual_brightness brightness max_brightness subsystem/ uevent bl_power device/ power/ type
可以通过读取 max_brightness
来显示最大亮度,通常为 15。
$ cat /sys/class/backlight/acpi_video0/max_brightness
15
可以通过将数字写入 brightness
来设置亮度。尝试设置大于最大值的亮度会导致错误。
# echo 5 > /sys/class/backlight/acpi_video0/brightness
默认情况下,只有 root
可以通过此方法更改亮度。要允许 video
组中的用户更改亮度,可以使用如下的 udev 规则(可能需要注销/重启才能使更改生效)
/etc/udev/rules.d/backlight.rules
ACTION=="add", SUBSYSTEM=="backlight", RUN+="/bin/chgrp video $sys$devpath/brightness", RUN+="/bin/chmod g+w $sys$devpath/brightness"
内核命令行选项
有时,由于主板实现和 ACPI 缺陷的不同,ACPI 无法很好地工作。这会导致例如不准确的亮度通知。这包括一些具有双显卡的笔记本电脑(例如,NVIDIA/AMD 独立 GPU 与 Intel/AMD 集成 GPU)。此外,即使已经存在一个背光(例如 intel_backlight
),ACPI 有时也需要注册自己的 acpi_video0
背光,这可以通过添加以下 内核参数 之一来完成
acpi_backlight=video acpi_backlight=vendor acpi_backlight=native
Udev 规则
如果 ACPI 接口可用,则可以使用 udev 规则在启动时设置背光级别
/etc/udev/rules.d/81-backlight.rules
# Set backlight level to 8 SUBSYSTEM=="backlight", ACTION=="add", KERNEL=="acpi_video0", ATTR{brightness}="8"
setpci
在某些情况下(例如 Intel Mobile 945GME [1]),可以设置显卡的寄存器来调整背光。这意味着您通过直接操作硬件来调整背光,这可能存在风险,通常不是一个好主意。并非所有显卡都支持此方法。
使用此方法时,您需要首先使用 lspci
找出您的显卡在哪里。
# setpci -s 00:02.0 F4.B=0
外接显示器
显示数据通道命令接口 (DDC/CI) 可用于通过 I2C 与实现 显示器控制命令集 (MCCS) 的外接显示器通信。DDC 可以控制支持的显示器上的亮度、对比度、输入等。通常也可以通过 DDC 管理通过 屏幕显示 (OSD) 面板可用的设置。如果 /dev/i2c-*
设备不存在,则可能需要加载 内核模块 i2c-dev
。
ddcutil 可用于查询和设置亮度设置
# ddcutil capabilities | grep "Feature: 10"
Feature: 10 (Brightness)
# ddcutil getvcp 10
VCP code 0x10 (Brightness ): current value = 60, max value = 100
# ddcutil setvcp 10 70
或者,可以使用 ddcci-driver-linux-dkmsAUR 在 sysfs 中公开外接显示器。然后,在加载 ddcci
内核模块 后,可以使用任何 背光工具。
- 同时使用
ddcci
和i2c-dev
可能会导致资源冲突,例如Device or resource busy
错误。 - NVIDIA 专有驱动程序的用户可能需要在 Xorg 配置 的
Device
部分添加Option "RegistryDwords" "RMUseSwI2c=0x01; RMI2cSpeed=100"
,或者为nvidia
模块添加NVreg_RegistryDwords=RMUseSwI2c=0x01;RMI2cSpeed=100
内核模块参数。参见 [2] 和 [3]。 - 如果显示器上启用了已自动调整某些 VCP 功能的功能(例如 动态对比度 或 BenQ 的 Eye Care 技术),则
ddcutil
将无法设置某些 VCP 功能。 - 为了方便将屏幕亮度控制绑定到键盘快捷键,可以启用非超级用户访问相关 I2C 设备。这可以通过添加组
i2c
并配置 udev 将此组设置为 I2C 设备的所有者来实现。参见 [4]。 - 如果安装了 ddcutil,它提供了
/usr/share/ddcutil/data/90-nvidia-i2c.conf
文件,可以将其复制到/etc/X11/xorg.conf.d/
而不是手动编辑 Xorg 配置文件。它还为 udev 规则提供了/usr/share/ddcutil/data/60-ddcutil-i2c.rules
和/usr/share/ddcutil/data/60-ddcutil-usb.rules
。
关闭背光
关闭背光(例如,当锁定笔记本电脑时)可能有助于节省电池能量。理想情况下,以下命令应该适用于任何 Xorg 图形会话
$ xset dpms force off
背光应该在鼠标移动或键盘输入时再次开启。或者,可以使用 xset s
来达到类似的效果。
如果之前的命令不起作用,则 vbetool 可能有效。但是请注意,在这种情况下,必须手动再次激活背光。命令如下
$ vbetool dpms off
要再次激活背光
$ vbetool dpms on
例如,可以在使用 acpid 关闭笔记本电脑盖时使用它。
保存和恢复功能
systemd 软件包包含服务 systemd-backlight@.service
,默认情况下启用且为“静态”。它在关机时保存背光亮度级别,并在启动时恢复它。该服务使用 #ACPI 中描述的 ACPI 方法,为在 /sys/class/backlight/
中找到的每个文件夹生成服务。例如,如果有一个名为 acpi_video0
的文件夹,它将生成一个名为 systemd-backlight@backlight:acpi_video0.service
的服务。当使用其他方法在启动时设置背光时,建议通过设置 内核参数 参数 systemd.restore_state=0
来阻止 systemd-backlight 恢复背光。有关详细信息,请参见 systemd-backlight@.service(8)。
systemd-backlight@backlight:acpi_video1
用于 acpi_video1
)。此外,brilloAUR 和 lightAUR 工具支持保存和恢复功能。如果希望在每个用户的基础上恢复屏幕亮度,这两个工具可能更有用,但是没有提供 systemd 单元来实现此目的。
背光工具
video
(或 input
)组的成员修改亮度。软件包名称 | 控制键盘背光 | 对环境亮度做出反应 | 语言 | 许可证 | 备注 |
---|---|---|---|---|---|
acpilight | 是 | 否 | Python3 | GPL-3.0-or-later | 提供 "xbacklight" 可执行文件 |
backlight_controlAUR | 否 | 否 | C | MIT | 非常小巧且简单。支持相对调整。 |
blightAUR | 是 | 否 | Python3 | ISC | 使用 logind 接口。仅限于本地用户,但不需要 suid 或 video 组 membership。 |
brightdAUR | 否 | 否 | C | GPL-2.0 | 在一段时间没有用户输入时调暗屏幕。 |
brightnessctl | 是 | 否 | C | MIT | - |
brilloAUR | 是 | 否 | C | GPL-3.0-only | 支持平滑和相对调整。 |
clightAUR | 是 | 是 | C | GPL-3.0-or-later | 管理屏幕色温(仅限 Xorg)并在超时后平滑地调暗亮度。支持环境光传感器 [5]。可以将网络摄像头变成环境光传感器。 |
enlighten-gitAUR | 是 | 否 | C | GPL-3.0-or-later | - |
illum-gitAUR | 否 | 否 | C | AGPL-3.0 | 对按键做出反应。 |
lightAUR | 是 | 否 | C | GPL-3.0-only | 无依赖。不依赖于 X 服务器。 |
luxAUR | 否 | 否 | Shell | MIT | - |
macbook-lighterAUR | 是 | 是 | Bash | GPL | Macbook 屏幕/键盘背光 CLI 和环境光自动调整。 |
wlr-brightness-gitAUR | 否 | 否 | C | MIT | 也支持需要伽玛调整的较新的 OLED 显示器。使用 wlroots。 |
wlumaAUR | 是 | 是 | Rust | ISC | 基于屏幕内容和环境光的自动亮度调整。可以使用网络摄像头或时间来模拟环境光传感器。支持键盘和外接显示器。使用 wlroots。 |
ybacklightAUR | 否 | 否 | Perl | GPL-2.0 | 类似于 xbacklight 但使用 sysfs 驱动程序的小型 Perl 脚本。 |
xbacklight-notifyAUR | 否 | 否 | C | MIT | 用于 X11 的简单通知守护程序(读取 RandR 背光属性) |
acpi-backlight-notifyAUR | 否 | 否 | C | MIT | 用于 ACPI 接口的简单通知守护程序(读取 /sys/class/backlight/ ) |
xbacklight
可以使用 xorg-xbacklight 软件包设置亮度。
要将亮度设置为最大值的 50%
$ xbacklight -set 50
可以使用增量而不是绝对值,例如,将亮度增加或减少 10%
$ xbacklight -inc 10 $ xbacklight -dec 10
如果您收到“No outputs have backlight property”错误,那是因为 xrandr/xbacklight 没有在 /sys/class/backlight
中选择正确的目录。您可以通过在 /etc/X11/xorg.conf.d/20-video.conf
的设备部分中设置 Backlight
选项来指定目录。例如,如果目录名称为 intel_backlight
并且使用 Intel 驱动程序,则设备部分可以配置如下
/etc/X11/xorg.conf.d/20-intel.conf
Section "Device" Identifier "Intel Graphics" Driver "intel" Option "Backlight" "intel_backlight" EndSection
有关详细信息,请参见 FS#27677 和 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=651741。
如果您启用了 Intel 快速启动,您也可能会收到 No outputs have backlight property
错误。在这种情况下,尝试上述方法可能会导致 Xorg 在启动时崩溃。您应该禁用它以解决此问题。已知它会引起亮度控制问题,已知。
light
安装 lightAUR 并将您的用户添加到 video
用户组。
将背光亮度增加 5%
$ light -A 5
将背光亮度减少 5%
$ light -U 5
将背光亮度设置为 100%
$ light -S 100
配合 GNOME 使用 DBus
亮度也可以像 GNOME 控件一样进行调整。使用此方法,更改会反映在 GNOME UI 中。
$ gdbus call --session --dest org.gnome.SettingsDaemon.Power --object-path /org/gnome/SettingsDaemon/Power --method org.freedesktop.DBus.Properties.Set org.gnome.SettingsDaemon.Power.Screen Brightness "<int32 50>"
键盘控制的亮度步进也可以使用此方法实现。
$ gdbus call --session --dest org.gnome.SettingsDaemon.Power --object-path /org/gnome/SettingsDaemon/Power --method org.gnome.SettingsDaemon.Power.Screen.StepUp $ gdbus call --session --dest org.gnome.SettingsDaemon.Power --object-path /org/gnome/SettingsDaemon/Power --method org.gnome.SettingsDaemon.Power.Screen.StepDown
配合 KDE 使用 DBus
参见 https://userbase.kde.org/KDE_Connect/Tutorials/Useful_commands#Brightness_settings。
颜色校正
颜色校正不会改变背光功率,它只会修改视频 查找表:这意味着您的电池续航时间不会受到更改的影响。尽管如此,当没有可用的背光控制时(台式 PC 或配备 OLED 屏幕的笔记本电脑),它可能很有用。
- Clight — 旨在完全管理您的显示器的用户守护程序实用程序。它可以像 redshift 一样,根据当前时间管理屏幕色温。如果配置文件中既未设置纬度也未设置经度,它会尝试使用 geoclue 来检索用户位置。它还支持固定的日出和日落时间。
- colord-brightness — 通过 Wayland 和 Xorg 下的 colord-daemon 和 ICC 配置文件设置亮度(类似于 icc-brightness,但性能更好)。
- Gammastep — 色温调整工具,Redshift 的一个分支。
- icc-brightness — 通过应用 ICC 颜色配置文件来控制 OLED 显示屏亮度。
- Monica — 显示器校准工具。它作为 xgamma 的前端来更改伽玛校正。
- https://web.archive.org/web/20090815224839/http://www.pcbypaul.com/software/monica.html || monicaAUR
- xcalib — 轻量级显示器校准加载器,可以加载 ICC 显示器配置文件以在桌面应用程序之间共享。
- xgamma — 更改显示器的伽玛校正。
Wayland
Redshift 不支持 Wayland(尽管存在 补丁集)。但是可以在启动 compositor 之前在 tty 中应用所需的色温。例如
$ redshift -m drm -PO 3000
否则,一些 compositor 可以在运行时应用颜色校正
- 在 GNOME 上,可以使用内置的 夜灯。
- 在 KDE Plasma 上,可以使用内置的 KDE#夜灯。
- 在 Sway 和其他基于 wlroots 的 compositor 以及 Orbital 上,可以使用 Redshift 分支 gammastep、wlsunset、clightAUR 或 wl-gammarelayAUR。
Xorg:使用 xrandr 调整感知亮度
可以使用 xrandr 调整感知亮度。
要将感知亮度调整到高于其最大水平(上述针对 Nvidia 提到的注意事项同样适用)
$ xrandr --output output_name --brightness 2
这应该大致使图像中的亮度加倍。它会牺牲色彩质量来换取亮度,但这特别适用于环境光非常亮的情况(例如阳光)。
这也可以用于在黑暗的房间中降低感知亮度,方法是指定小于 1 的值(例如 0.5),这在没有背光控制的情况下很有用(例如台式 PC)。
可以通过调用 xrandr
来确定连接设备的输出名称
$ xrandr | grep -w connected | cut -f '1' -d ' '
用户可能会发现将其实现为别名很方便
$ alias b='echo -e "enter brightness:\n"; read val; xrandr --output output name --brightness "${val}"'
要在背光文件更改时自动调用 xrandr,可以使用 oled_shmoledAUR,如下所示
$ oled_shmoled output_name
NVIDIA 设置
NVIDIA 专有驱动程序的用户可以通过 nvidia-settings 实用程序在“X Server Color Correction”下更改显示亮度。但是,请注意,这与背光(强度)绝对无关,它仅仅调整颜色输出。(当所有其他选项都失败时,以这种方式降低亮度是一种低效的最后手段;以这种方式增加亮度会完全破坏您的颜色输出,类似于曝光过度的照片。)
故障排除
背光 PWM 调制频率(仅限 Intel i915)
已知带有 LED 背光的笔记本电脑有时会出现屏幕闪烁。这是因为控制 LED 背光亮度的最有效方法是通过非常快速地打开和关闭 LED 来改变它们开启的时间量。
但是,开关的频率,即所谓的 PWM(脉冲宽度调制)频率,可能不够高,以至于眼睛将其感知为单一亮度,而是看到闪烁。这会导致某些人出现头痛和眼睛疲劳等症状。
如果您有 Intel i915 GPU,则可以调整 PWM 频率以消除闪烁。
PWM 的周期(频率的倒数)存储在 0xC8254
寄存器的 2 个高位字节中(如果您使用的是 Intel GM45 芯片组,请使用地址 0x61254
代替)。要操作寄存器值,安装 intel-gpu-tools 软件包。
要增加频率,必须减小周期。例如
# intel_reg read 0xC8254
0xC8254 : 0x12281228
然后,要将 PWM 频率加倍,请将 2 个高位字节(4 个高位十六进制数字)除以 2,然后写回结果值,保持低位字节不变
# intel_reg write 0xC8254 0x09141228
您可以使用在线计算器计算所需的值 https://devbraindom.blogspot.com/2013/03/eliminate-led-screen-flicker-with-intel.html
要自动设置新频率,请考虑编写 udev 规则或安装 intelpwm-udevAUR。
亮度反转(仅限 Intel i915)
症状
- 安装 xf86-video-intel 后,systemd-backlight.service 在启动期间关闭背光
- 可能的解决方案:屏蔽 systemd-backlight.service
- 从 X 切换到另一个 VT 会关闭背光
- 亮度键已反转(即,调高亮度会使屏幕变暗)
可以通过将 i915.invert_brightness=1
添加到 内核参数 列表中来解决此问题。
无法控制 eDP 面板亮度(仅限 Intel i915)
嵌入式显示端口 (eDP) v1.2 引入了一种新的显示面板控制协议,用于背光和其他控件,该协议通过 AUX 通道工作 [7]
默认情况下,i915 驱动程序尝试使用 PWM 来控制背光亮度,这可能不起作用。
要通过写入 DPCD 寄存器使用 AUX 通道设置背光,请将 i915.enable_dpcd_backlight=1
设置为 内核参数。
sysfs 已修改但亮度没有变化
在某些系统中,键盘上的亮度热键可以正确修改 /sys/class/backlight/acpi_video0/actual_brightness
中 acpi 接口的值,但屏幕亮度却没有改变。桌面环境的亮度小程序也可能显示已更改,但实际上无效。
如果您已测试过推荐的内核参数,且只有 xbacklight
有效,那么您可能遇到了 BIOS 和内核驱动程序之间的不兼容问题。
在这种情况下,唯一的解决方案是等待 BIOS 或 GPU 驱动程序制造商发布修复程序。
一种权宜之计是使用 inotify 内核 API,以便在每次 /sys/class/backlight/acpi_video0/actual_brightness
的值发生更改时触发 xbacklight
。
首先安装 inotify-tools。然后创建一个基于 inotify 的脚本,该脚本将在每次启动时或通过自启动启动。
/usr/local/bin/xbacklightmon
#!/bin/sh path=/sys/class/backlight/acpi_video0 luminance() { read -r level < "$path"/actual_brightness factor=$(printf "$max" | awk '{print 100/$1}') printf "$level $factor" | awk '{print int($1*$2)}' } read -r max < "$path"/max_brightness xbacklight -set "$(luminance)" inotifywait -me modify --format '' "$path"/actual_brightness | while read; do xbacklight -set "$(luminance)" done
sysfs 和 xbacklight 均不工作
检查 dmesg,看看是否看到类似这样的信息
i915 0000:00:02.0: [drm] *ERROR* [CONNECTOR:114:DSI-1] 无法获取 SoC PWM 芯片
修改 /etc/mkinitcpio.conf
以匹配以下内容
/etc/mkinitcpio.conf
... MODULES=(i915 pwm-lpss-platform) ...
MATE 中背光不工作
确保已安装 mate-power-manager 软件包。
Xfce 中背光按键不工作
在 xfce4 中,Xfce4 电源管理器处理亮度按键。
在某些 Xfce 安装中,“处理显示器亮度按键”设置可能默认关闭。
要重新激活亮度按键,请打开Xfce 电源管理器对话框并启用“处理显示器亮度按键”。
$ xfce4-power-manager -c
xbacklight 返回:No outputs have backlight property
根据安装的显卡,有时来自 xorg-xbacklight 的 xbacklight 会返回消息 “No outputs have backlight property”。 安装 acpilight 提供了另一种 xbacklight,可能可以按预期工作。
使用 amdgpu 驱动程序重启后,背光始终处于最大亮度
由于最近在 amdgpu 驱动程序中引入的 bug,背光的 actual_brightness
值被报告为 16 位整数,这超出了 max_brightness
中指定的 8 位范围。 这导致 systemd-backlight
服务尝试在启动时恢复一个过大的值,最终被截断为最大亮度 (255)。
在 bug 尚未解决时,一种可能的权宜之计是在恢复之前将存储的亮度修改到正确的范围内。 这可以通过脚本和服务单元来完成。
fix-brightness.sh
#!/bin/bash # Change the line below according to your hardware BRIGHTNESS_FILE="/var/lib/systemd/backlight/pci-0000:04:00.0:backlight:amdgpu_bl0" BRIGHTNESS=$(cat "$BRIGHTNESS_FILE") BRIGHTNESS=$(($BRIGHTNESS*255/65535)) BRIGHTNESS=${BRIGHTNESS/.*} # truncating to int, just in case echo $BRIGHTNESS > "$BRIGHTNESS_FILE"
fix-brightness.service
[Unit] Description=Convert 16-bit brightness values to 8-bit before systemd-backlight applies it Before=systemd-backlight@backlight:amdgpu_bl0.service [Service] Type=oneshot ExecStart=/path/to/fix-brightness.sh [Install] WantedBy=multi-user.target
在某些系统上,驱动程序报告的背光级别在正确的范围 [0, 255] 内,但 systemd 仍然无法恢复正确的值。 这可能是由于 kernel 中的竞争条件引起的。 在这种情况下,由于亮度级别已在正确的范围内,因此截断亮度级别将无济于事。 相反,在关机前将亮度级别保存到 systemd 可能会作为一种权宜之计。 这可以通过以下脚本和服务单元来完成。
fix-brightness.sh
#!/bin/sh # Backlight level from systemd's perspective (change if needed) readonly SYSTEMD_BACKLIGHT_FILE='/var/lib/systemd/backlight/pci-0000:04:00.0:backlight:amdgpu_bl0' # Backlight level from AMDGPU driver readonly AMDGPU_BACKLIGHT_FILE='/sys/class/backlight/amdgpu_bl0/brightness' # Read current value from the driver and apply it to systemd readonly AMDGPU_BACKLIGHT_VALUE=$(cat "$AMDGPU_BACKLIGHT_FILE") echo "$AMDGPU_BACKLIGHT_VALUE" > "$SYSTEMD_BACKLIGHT_FILE"
fix-brightness.service
[Unit] Description=Save brightness value from AMDGPU DefaultDependencies=no After=final.target [Service] Type=oneshot ExecStart=/path/to/fix-brightness.sh [Install] WantedBy=final.target
<5% 亮度在重启后仍然保留(禁用背光钳制)
根据 systemd-backlight@.service(8),如果 udev 属性 ID_BACKLIGHT_CLAMP
未设置为 false,则亮度将被钳制为至少最大亮度的 1% 或 5%(以较大者为准)。 当内核允许用户空间可靠地设置不会关闭显示器的亮度值时,此限制将被取消。
要允许 <5% 亮度在重启后仍然保留,请创建 udev 规则
/etc/udev/rules.d/99-backlight_clamp.rules
# Allow <5% brightness to persist on reboot (disable clamped value of 5%) SUBSYSTEM=="backlight", ENV{ID_BACKLIGHT_CLAMP}="0"