背光
螢幕亮度調節可能有點難以控制。在一些電腦上,可能缺失了物理硬體開關,並且軟體解決方案也可能工作得不好。但是通常地,我們可以對於給定的硬體,找到對應的方法來調節螢幕亮度。本文旨在總結所有可能的調節螢幕亮度和背光(Backlight)的方法。
我們有很多方法可以用來控制顯示器、筆記本電腦或者集成面板(比如 iMac)。根據這些(英文)討論(英文)和這個維基頁面(英文),控制的方法可以分為以下幾種:
- 亮度由供應商指定的熱鍵控制,而作業系統沒有對應的介面用於調節螢幕亮度。
- 亮度由 ACPI,圖形或者平台的驅動來控制。在這種情況下,亮度控制透過
/sys/class/backlight
暴露給使用者。使用者空間基於此,提供了背光實用程式。 - 可以透過 setpci 來寫入到顯示卡的暫存器,來控制亮度。
硬體介面[編輯 | 編輯原始碼]
ACPI[編輯 | 編輯原始碼]
螢幕背光的亮度由背光LED或陰極的電平來調節,且通常由影片ACPI核心模組調節。此模組的介面以位於/sys/class/backlight/
的sysfs(5)目錄的形式提供。
具體的目錄名稱由顯示卡型號決定。
$ 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/Radeon獨顯+Intel/AMD集顯)。此外,ACPI有時需要註冊自己的acpi_video0
背光源,即使已經存在一個背光源(如intel_backlight
),這可以透過添加以下核心參數之一來完成:
acpi_backlight=video acpi_backlight=vendor acpi_backlight=native
如果更改acpi_video0
背光源無法真正更改亮度,可能需要使用acpi_backlight=none
。
- 在使用NVIDIA Optimus的筆記本上,核心參數
nomodeset
可能與背光調節衝突。 - 在華碩(ASUS)筆記本上可能需要載入
asus-nb-wmi
核心模組。 - 在Dell XPS 13上禁用Legacy boot會導致背光支援異常。
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可以在受支援的顯示器上控制亮度、對比度、輸入等。可以透過OSD(螢幕選單,On-Screen Display)面板操作的設定通常也可以透過DDC管理。如果/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專有驅動的使用者可能需要向
/etc/X11/xorg.conf.d/20-nvidia.conf
(由nvidia-xconfig生成)的Device
部分添加Option "RegistryDwords" "RMUseSwI2c=0x01; RMI2cSpeed=100"
,或向/etc/modprobe/conf.d/nvidia.conf
添加options nvidia NVreg_RegistryDwords=RMUseSwI2c=0x01;RMI2cSpeed=100
。使用grep RegistryDwords /proc/driver/nvidia/params
命令,並檢查其中的值是否為空來驗證設定是否被正確應用。參見[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/45-ddcutil-i2c.rules
和/usr/share/ddcutil/data/45-ddcutil-usb.rules
。
關閉背光[編輯 | 編輯原始碼]
關閉背光(Backlight)(比如說當鎖屏的時候),可以有效地保護電源電量。理想情況下,在Xorg圖形對談中,下列命令應該可以執行:
$ xset dpms force off
這個背光(Backlight)可以透過滑鼠的移動或者鍵盤的輸入來再次開啟。或者,xset s
應該可以用來完成相似的作用。
如果上面的命令沒有完成,那麼可能是因為 vbetool 起作用。注意,然而,在這種情況下,背光(Backlight)必須手動再次開啟,(關閉背光的)命令如下:
$ 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-backlight服務恢復背光,只需要設定核心參數systemd.restore_state=0
。參見systemd-backlight@.service(8)。
acpi_video1
則禁用systemd-backlight@backlight:acpi_video1
)。此外,brilloAUR和light包等實用程式也有儲存與恢復背光的能力。提及到的這兩個可以為每個使用者單獨恢復螢幕亮度(尚無systemd單元支援這麼做)。
背光實用程式[編輯 | 編輯原始碼]
video
(或input
)使用者群組的成員更改亮度。包名 | 控制鍵盤背光 | 適應環境光 | 語言 | 許可協定 | 注釋 |
---|---|---|---|---|---|
acpilight包 | 是 | 否 | Python3 | GPL-3.0-or-later | 提供"xbacklight"可執行程式 |
backlight_controlAUR | 否 | 否 | C | MIT | 非常小巧和簡單。支援相對調整。 |
blightAUR | 是 | 否 | Python3 | ISC | 使用logind介面。僅限於本地使用者,但不要求為suid或video使用者群組成員。 |
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 | 會對按鍵做出反應。 |
light包 | 是 | 否 | C | GPL-3.0-only | 無額外依賴。不依賴X伺服器。 |
luxAUR | 否 | 否 | Shell | MIT | - |
macbook-lighterAUR | 是 | 是 | Bash,Perl | 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 | 簡單的通知守護行程 |
XF86MonBrightnessUp
和XF86MonBrightnessDown
鍵盤按鍵。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
中設定Device(裝置)部分的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 Fastboot,也有可能會報錯No outputs have backlight property
。這種情況下,使用以上方法可能導致Xorg在啟動時崩潰。此時建議禁用Intel Fastboot以解決問題。已知這會導致亮度控制的問題。
light[編輯 | 編輯原始碼]
安裝light包並將你使用的使用者添加到video
使用者群組。
將背光亮度提高5%:
$ light -A 5
將背光亮度降低5%:
$ light -U 5
將背光亮度設為100%:
$ light -S 100
在GNOME中使用DBus[編輯 | 編輯原始碼]
亮度也可以像GNOME設定那樣進行調整。使用此方法時,GNOME的使用者介面會反映出所做的更改。
$ 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 。
色彩校正[編輯 | 編輯原始碼]
色彩校正並不會改變實際背光的功率,僅僅只是修改影片尋找表。也就是說,這樣並不會像上述方法一樣,調低亮度就可以節省電量。無論如何,如果背光控制完全不可用的時候(比如使用OLED螢幕的桌上型電腦和筆記本),可以嘗試用色彩校正。
- Clight — 旨在全面管理顯示器的使用者守護程式實用程式。它可以根據一天中的目前時間來管理螢幕溫度,就和Redshift一樣。如果設定檔中未設定緯度或經度,它將嘗試使用geoclue包來檢索使用者位置。它也支援日出和日落的固定時間。
- 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(除非打修補程式或者使用衍生版本,比如redshift-wayland-gitAUR)。但是仍可以在啟動混成器前在tty中應用想要的色溫設定。比如:
$ redshift -m drm -PO 3000
或者,部分混成器也支援執行時應用色彩校準:
- GNOME可以使用內建的夜間模式。
- KDE Plasma也可以使用內建的夜間模式。
- Sway 1.0或其他基於wlroots的混成器,包括Orbital,可以使用Redshift的衍生版本、gammastep包、clightAUR、wlsunset-gitAUR、wl-gammarelayAUR。
Xorg:使用xrandr調節視覺亮度[編輯 | 編輯原始碼]
xrandr可以用於調節視覺亮度。
要將視覺亮度調至最大值以上(其問題與上方提到的NVIDIA設定的情況相同):
$ xrandr --output output_name --brightness 2
這會將畫面亮度翻倍(大致上),但是這麼調高亮度會犧牲色彩的品質,但它特別適合環境光非常明亮的情況下(如陽光直射)。
也可以指定小於1(例如 0.5)的值來降低視覺亮度,這在顯示裝置位於暗處且沒有背光控制可用時(例如桌上型電腦)是有用的。
例子中的所連接裝置的output name(輸出名稱)可以透過調用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,改變它們開啟的時間長度。
然而,LED開關的頻率,即所謂的PWM(脈寬調製)頻率,可能不夠高,以至於眼睛無法將其感知為恆定的亮度,而是看到閃爍的情況。這會導致一些人出現頭痛和眼睛疲勞等症狀。
如果使用Intel i915 GPU,則可以調整PWM頻率以消除閃爍現象。
PWM的周期(與頻率互為倒數)儲存於0xC8254
暫存器的兩個高位位元組(如果使用Intel GM45晶片組,則暫存器位址為0x61254
)。要操作暫存器的值,請從官方源安裝intel-gpu-tools包。
要增加頻率,就需要減少周期。比如:
# intel_reg read 0xC8254
0xC8254 : 0x12281228
要將PWM頻率加倍,請將兩個高位位元組(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在系統啟動時將背光關閉
- 可能的解決方案:封鎖(mask)systemd-backlight.service
- 從X切換到另一個虛擬終端(VT)會關閉背光
- 亮度調節鍵/按鈕效果相反(即按亮度+反而會讓螢幕變暗)
可透過添加i915.invert_brightness=1
至核心參數列表來解決這個問題。
無法控制eDP面板亮度(僅Intel i915)[編輯 | 編輯原始碼]
嵌入式顯示埠(eDP)v1.2 為透過AUX通道工作的背光和其他控制項引入了新的顯示面板控制協定 [7]
預設情況下,i915驅動可能嘗試使用PWM調節背光亮度,此時可能無法工作。
要透過使用AUX通道寫入DPCD暫存器來設定背光,請設定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=$((100 / max)) printf '%d\n' "$((level * factor))" } read -r max < "$path"/max_brightness xbacklight -set "$(luminance)" inotifywait -me modify --format '' "$path"/actual_brightness | while read; do xbacklight -set "$(luminance)" done
MATE下背光不工作[編輯 | 編輯原始碼]
Xfce下背光按鍵不工作[編輯 | 編輯原始碼]
在xfce4中,Xfce4電源管理器處理亮度按鍵。
在部分Xfce環境中,「處理顯示亮度按鍵」(Handle display brightness keys)的設定可能預設為關閉。
要再次啟用亮度按鍵,開啟Xfce4電源管理器對話方塊並開啟「處理顯示亮度按鍵」:
$ 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
值可能返回十六位整型數值,而max_brightness
中指定的數值為八位。這會導致systemd-backlight
服務在系統啟動時嘗試恢復亮度,但嘗試恢復到的亮度值總是大於最大亮度值,進而變成調為最大亮度(255)。
在該錯誤沒有得到解決的期間,一種可能的解決方法是在恢復之前將儲存的亮度修改(截斷)到正確的範圍內。這可以透過腳本和服務單元來完成:
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 the script above> [Install] WantedBy=multi-user.target
在部分系統上,驅動返回的背光等級確實在正確的範圍[0, 255]內,但systemd仍然不能恢復為正確的亮度值。這有可能是由於核心中的衝突。這種情況下,截斷亮度等級沒有用處,因為已經在正確範圍內。臨時的解決方法包括在關機前向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=<到上方腳本的路徑> [Install] WantedBy=final.target