1 问题描述
CPU:G6900E
OS:ubuntu22.04
Kernel:6.8.0-49-generic
系统下有两个一样的 edp 屏幕,投影模式选择“只使用外部”,内部 edp 屏幕灭,外部 edp 屏幕无背光。DP-1 是外部 edp 屏幕,eDP-1 是内部 edp 屏幕,使用“xrandr --output eDP-1 --off”命令关闭内部 edp 屏幕,效果也是内部 edp 屏幕灭,外部 edp 屏幕无背光。
2 解决过程
2.1 尝试调节背光
在系统上查找背光调节节点,命令如下所示,发现两个 edp 屏幕共用内部 edp 屏幕背光调节节点,都是“/sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness”。
jw@jw-Windows-cpmpact-G6900E:~$ sudo find / -name brightness
/sys/devices/pci0000:00/0000:00:14.3/leds/phy0-led/brightness
/sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness
/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1:1.0/0003:1C4F:0002.0002/input/input6/input6::numlock/brightness
/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1:1.0/0003:1C4F:0002.0002/input/input6/input6::scrolllock/brightness
/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1:1.0/0003:1C4F:0002.0002/input/input6/input6::capslock/brightness
在投影模式为“镜像”或者“拼接显示器”模式下时,修改内部 edp 屏幕背光调节节点的值,命令如下所示,两个 edp 屏幕的背光一起变化。在投影模式“只使用外部模式下”,修改内部 edp 屏幕背光调节节点值,外部 edp 屏幕背光无变化。
root@jw-Windows-cpmpact-G6900E:/home/jw# cat /sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness
96000
root@jw-Windows-cpmpact-G6900E:/home/jw# echo 30000 > /sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness
root@jw-Windows-cpmpact-G6900E:/home/jw# echo 96000 > /sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness
2.2 尝试设置主次屏幕
默认情况下内部 edp 屏幕(eDP-1)为主屏幕,外部 edp 屏幕(DP-1)为次屏幕,将外部屏幕设置为主屏幕,命令为“xrandr --auto --output DP1 --primary”,投影模式选择“只使用外部”,效果也是内部 edp 屏幕灭,外部 edp 屏幕无背光,修改内部 edp 屏幕背光调节节点的值,外部 edp 屏幕背光无变化。
2.3 尝试修改驱动
2.3.0 编译新内核 deb 包
给 ubuntu 20.04/22.04/24.04 编译换上最新的 6.12 内核(生成 deb 包) - Ubuntu中文论坛,在该网站有 ubuntu 相应的内核和 补丁可以下载。
下载对应内核版本和补丁。
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.8.tar.xz
wget https://forum.ubuntu.com.cn/download/file.php?id=195233&sid=d2ce50a2ba3b3f8ed6b52cafa4a7ab10
编译内核生成 deb 包,相应的操作命令如下所示。
tar Jxf linux-6.8.tar.xz
mv linux-6.8 linux-6.8.0
mv linux-6.8.0.diff.zst.txt linux-6.8.0.diff.zst
zstd -d linux-6.8.0.diff.zst
cd linux-6.8.0
patch -p1 <../linux-6.8.0.diff
chmod +x debian/rules
chmod +x -R debian/scripts/*
debuild
编译完成生成的 deb 包在上一级目录,如下所示。
zwzn2064@zwzn2064-CVN-Z690D5-GAMING-PRO:~/sda1/elo_kernel/linux-6.8.0$ ls ../*.deb
../linux-buildinfo-6.8.0-3-generic_6.8.0-3.10_amd64.deb ../linux-libc-dev_6.8.0-3.10_amd64.deb
../linux-cloud-tools-common-6.8.0_6.8.0-3.10_all.deb ../linux-modules-6.8.0-3-generic_6.8.0-3.10_amd64.deb
../linux-doc_6.8.0-3.10_all.deb ../linux-source-6.8.0_6.8.0-3.10_all.deb
../linux-headers-6.8.0-3_6.8.0-3.10_all.deb ../linux-tools-common-6.8.0_6.8.0-3.10_all.deb
../linux-headers-6.8.0-3-generic_6.8.0-3.10_amd64.deb ../linux-tools-host-6.8.0_6.8.0-3.10_all.deb
../linux-image-6.8.0-3-generic_6.8.0-3.10_amd64.deb
zwzn2064@zwzn2064-CVN-Z690D5-GAMING-PRO:~/sda1/elo_kernel/linux-6.8.0$
将这些 deb 包安装到系统上,相应的操作命令如下所示。安装后,重启系统不断按下“Shift”,即可选择新安装的内核版本启动系统。
sudo dpkg -i *.deb
sudo update-grub
2.3.1 修改驱动
控制 edp 屏幕背光的驱动代码为“drivers/gpu/drm/i915/display/intel_backlight.c”。调节背光的函数为“bxt_set_backlight”,加上打印,输出寄存器和值,编译成 deb 包安装到系统里面启动。投影模式选择“只使用外部”,使用 dmesg 打印日志,发现有对一个寄存器写值为 0。怀疑是不是这个动作引起了这个 bug,将这个“bxt_set_backlight ”函数的功能注释掉,编译成 deb 包安装进系统,投影模式选择“只使用外部”,bug 没有解除。
drivers/gpu/drm/i915/display/intel_backlight.c
static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_panel *panel = &connector->panel;
intel_de_write(i915, BXT_BLC_PWM_DUTY(panel->backlight.controller), level);
}
既然 bug 与背光 pwm 调节寄存器无光,那可能是与背光 pwm 使能寄存器有关,搜索"disable_backlight"相关函数,相应的函数如下所示。
zwzn2064@zwzn2064-CVN-Z690D5-GAMING-PRO:~/sda1/elo_kernel/linux-6.8.0$ grep -rn "disable_backlight" drivers/gpu/drm/i915/display/intel_backlight.c
333:static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level)
359:static void pch_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
371:static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
376:static void i965_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
385:static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
396:static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
411:static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
425:static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level)
1600:static void intel_pwm_disable_backlight(const struct drm_connector_state *conn_state, u32 level)
1703: .disable = bxt_disable_backlight,
1712: .disable = cnp_disable_backlight,
1721: .disable = lpt_disable_backlight,
1730: .disable = lpt_disable_backlight,
1739: .disable = pch_disable_backlight,
1748: .disable = ext_pwm_disable_backlight,
1756: .disable = vlv_disable_backlight,
1765: .disable = i965_disable_backlight,
1774: .disable = i9xx_disable_backlight,
1783: .disable = intel_pwm_disable_backlight,
这些函数都加上“printk( %s\n", __func__)”,编译成 deb 包,安装进内核,投影模式选择“只使用外部”,使用 dmesg 打印日志,发现输出“cnp_disable_backlight”,怀疑是这个函数关闭了背光 pwm 使能,注释掉这个函数的功能,如下所示,bug 成功解决。
zwzn2064@zwzn2064-CVN-Z690D5-GAMING-PRO:~/sda1/elo_kernel/linux-6.8.0$ git diff
diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c
index 3f3cd944a..b5d660877 100644
--- a/drivers/gpu/drm/i915/display/intel_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_backlight.c
@@ -410,6 +410,7 @@ static void bxt_disable_backlight(const struct drm_connector_state *old_conn_sta
static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
{
+ /*
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_panel *panel = &connector->panel;
@@ -418,6 +419,7 @@ static void cnp_disable_backlight(const struct drm_connector_state *old_conn_sta
intel_de_rmw(i915, BXT_BLC_PWM_CTL(panel->backlight.controller),
BXT_BLC_PWM_ENABLE, 0);
+ */
}
3 自动进入新的内核驱动系统
将内核 deb 包安装进系统后,每次在系统重启都要按“Shift”选择新的内核版本进行启动,如下所示,很麻烦。
可以修改“/etc/default/grub”配置文件,系统在每次重启或开机时自动选择新的内核版本启动。原始“/etc/default/grub”配置文件如下所示。因为“6.8.0-3-generic”内核排列在“6.8.0-49-generic”后面第二个,所以将“GRUB_DEFAULT=0”改成“GRUB_DEFAULT="1> 2"”,然后执行“sudo update-grub”,即可每次重启系统都选择“6.8.0-3-generic”内核启动。
# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.
# For full documentation of the options in this file, see:
# info -f grub -n 'Simple configuration'
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""
# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console
# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=640x480
# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true
# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"
# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"