Bug 76811 - Kernel sets wrong screen brightness resuming from suspend on Optimus enabled laptop
Summary: Kernel sets wrong screen brightness resuming from suspend on Optimus enabled ...
Status: CLOSED DOCUMENTED
Alias: None
Product: ACPI
Classification: Unclassified
Component: Power-Video (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Aaron Lu
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-24 02:31 UTC by JU
Modified: 2014-07-02 08:23 UTC (History)
3 users (show)

See Also:
Kernel Version: 3.14.4
Subsystem:
Regression: No
Bisected commit-id:


Attachments

Description JU 2014-05-24 02:31:37 UTC
Originally, I thought this was a systemd bug. I am completely unsure what subsection this bug should be filed against; apologies. Since Lennart Poettering suggested against "the kernel driver", I will assume he means the Intel driver. Feel free to move it. I am unsure whether this is a regression or whether its never been seen. I can confirm that the problem remains on kernel version 3.10.40 (Arch's LTS kernel), and also on Debian's current testing kernel (3.14). 

Here is the link to the bug report filed against systemd:
https://bugs.freedesktop.org/show_bug.cgi?id=79159

I will paste the description from that bug below and Lennart's response:

"On systems with only one graphics card (or with Optimus disabled in BIOS), systemd (note: I now realize the kernel) works correctly: whatever the screen brightness when suspend is initiated is the screen brightness that is set upon resuming from suspend. 

If the system has Optimus enabled however, resuming from suspend always sets the backlight to 100%. This is because systemd (note: I now realize the kernel) is apparently looking at the wrong device in /sys/class/backlight (the device of the nvidia card, not the intel card which controls the backlight).

Consider the following contents of /sys/class/backlight on a system with Optimus disabled:
$ ls /sys/class/backlight
acpi_video0  intel_backlight

Now consider the results of a system with Optimus enabled:
$ ls /sys/class/backlight
acpi_video0  acpi_video1  intel_backlight

In the second case, if I manually:
echo "50" > /sys/class/backlight/acpi_video1/brightness
the laptop will resume from suspend with 50% screen brightness (regardless of what the brightness is actually set at).

Information:
Lenovo Thinkpad T530
EFI setup
Arch Linux (64bit) (Fully up to date as of this posting)
systemd version: 212 (or: 212-3 in the Arch repos)
lspci | grep "VGA" (Optimus enabled)
00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics Controller (rev 09)
01:00.0 VGA compatible controller: NVIDIA Corporation GF108M [NVS 5400M] (rev a1)


I am not sure whether this is a regression or if it has just never came up- I only recently starting using Optimus (having disabled it via BIOS before) so..

If you need any other information, just ask :)"

Response from Lennart Poettering:
"systemd doesn't save/restore backlight settings across suspend/resume, only across reboots, hence is not involved. AFAIK the kernel is responsible for doing that part on its own, hence please file a bug against the kernel driver. Thanks!"
Comment 1 JU 2014-05-24 02:49:11 UTC
A link to the Archlinux bug report:
https://bugs.archlinux.org/task/40518
Comment 2 Jani Nikula 2014-05-26 09:19:57 UTC
What driver do you use for optimus?

Which ones of the interfaces at /sys/class/backlight change the backlight brightness if you echo there? (Note the potentially differing max_brightness values.)

Echo distinct values to the brightness, cat brightness and actual_brightness for each and paste here, do a suspend/resume, and repeat the cat and paste.
Comment 3 JU 2014-05-26 23:01:07 UTC
(In reply to Jani Nikula from comment #2)
> What driver do you use for optimus?
Driver? I use bumblebee and primusrun, though the bug exists whether bumblebeed is enabled or not.

As for video drivers, I use xf86-video-intel and proprietary nvidia drivers (both installed from the Arch repos; no 3rd party builds).
 
> Which ones of the interfaces at /sys/class/backlight change the backlight
> brightness if you echo there? (Note the potentially differing max_brightness
> values.)
> 
> Echo distinct values to the brightness, cat brightness and actual_brightness
> for each and paste here, do a suspend/resume, and repeat the cat and paste.

===Before suspend/resume, backlight at 50% (set with brightness keys on keyboard, no xorg-xbacklight isntalled)===

cat /sys/class/backlight/intel_backlight/brightness   --->  578
cat /sys/class/backlight/intel_backlight/actual_brightness   --->  578
cat /sys/class/backlight/intel_backlight/max_brightness   ---> 4437
echo "4437" > /sys/class/backlight/intel_backlight/brightness   ---> Seems to go full bright
echo "0" > /sys/class/backlight/intel_backlight/brightness   ---> Literally kills the backlight
echo "<some number>" > /sys/class/backlight/intel_backlight/actual_brightness   ---> permission denied (ran as root)
Note: if I echo a number between 0 and 4437 to .../intel_backlight/brightness, the brightness scales (higher numbers = brighter screen). 50% brightness equates to 578 strangely.


cat /sys/class/backlight/acpi_video1/max_brightness   ---> 100
cat /sys/class/backlight/acpi_video1/actual_brightness   ---> 50
cat /sys/class/backlight/acpi_video1/brightness   ---> 50
echo "100" > /sys/class/backlight/acpi_video1/brightness   ---> screen goes full bright
echo "10" > /sys/class/backlight/acpi_video1/brightness   ---> Screen goes full dim, but is still visible
echo "<some number>" > /sys/class/backlight/acpi_video1   ---> permission denied (ran as root)
Note: if I echo a number between 10 and 100, the screen brightness scales as expected


cat /sys/class/backlight/acpi_video0/max_brightness   ---> 100
cat /sys/class/backlight/acpi_video0/actual_brightness   ---> 50
cat /sys/class/backlight/acpi_video0/brightness   ---> 50
echo "100" > /sys/class/backlight/acpi_video0/brightness   ---> Screen full bright.
echo "10" > /sys/class/backlight/acpi_video0/actual_brightness   ---> permission denied (ran as root)

Time to suspend.

Heres where it gets complicated:

1) When I resume from suspend, the kernel reads the value from /sys/class/backlight/acpi_video1/brightness. I know this because:
	A) echo "100" > /sys/class/backlight/acpi_video1/brightness
	B) echo "50" > /sys/class/backlight/acpi_video0/brightness
	C) Suspend
	Result: Computer goes into suspend at half screen brightness, and comes out of suspend full bright.
If instead I do the following:
	A) echo "100" > /sys/class/backlight/acpi_video0/brightness
	B) echo "50" > /sys/class/backlight/acpi_video1/brightness
	C) Suspend
	Result: Computer goes into suspend at half screen brightness, and comes out of suspend at half brightness.
2) The brightness keys change the value of .../acpi_video0/brightness and NOT .../acpi_video1/brightness. Yet whatever value is echoed to .../acpi_video1/brightness is the value the kernel sets the screen brightness from after resuming from suspend.

/sys/class/backlight/intel_backlight/brightness changes no matter whether I use the brightness keys, or echo manually to acpi_video0 and acpi_video1 brightness files.

Note: All the cat and echoing I did in the first 3 paragraphs functions exactly the same when doing them after suspend.

Summary: The kernel is checking the brightness file on acpi_video1, yet when the kernel changes the screen brightness using the brightness keys on the keyboard, it changes the brightness file value of acpi_video0. Thus, anytime one resumes from suspend, the kernel will choose the wrong device to read brightness values from.

I think it may be possible to cheat with Xorg by setting a rule in the xorg.conf. I should note that when Optimus is disabled in BIOS, suspend works fine (only the intel card is seen by Linux).

Also, heres a snippet from journalctl that might be of interest to you:
May 26 17:12:14 codething kernel: Non-volatile memory driver v1.3
May 26 17:12:14 codething kernel: thinkpad_acpi: ThinkPad ACPI Extras v0.25
May 26 17:12:14 codething kernel: thinkpad_acpi: http://ibm-acpi.sf.net/
May 26 17:12:14 codething kernel: thinkpad_acpi: ThinkPad BIOS G4ET98WW (2.58 ), EC unknown
May 26 17:12:14 codething kernel: thinkpad_acpi: Lenovo ThinkPad T530, model 2359CTO
May 26 17:12:14 codething kernel: thinkpad_acpi: Unsupported brightness interface, please contact ibm-acpi-devel@lists.sourceforge.net
May 26 17:12:14 codething kernel: thinkpad_acpi: radio switch found; radios are enabled
May 26 17:12:14 codething kernel: thinkpad_acpi: This ThinkPad has standard ACPI backlight brightness control, supported by the ACPI video driver
May 26 17:12:14 codething kernel: thinkpad_acpi: Disabling thinkpad-acpi brightness events by default...
May 26 17:12:14 codething kernel: thinkpad_acpi: rfkill switch tpacpi_bluetooth_sw: radio is unblocked
May 26 17:12:14 codething kernel: thinkpad_acpi: Console audio control enabled, mode: monitor (read only)
May 26 17:12:14 codething kernel: input: PC Speaker as /devices/platform/pcspkr/input/input8


Whew, I hope that wasnt too confusing; I tried to be clear. Let me know if you need any other info.
Comment 4 Jani Nikula 2014-05-27 06:14:13 UTC
On resume, ACPI video driver restores the backlight brightness on all devices that have a backlight interface, in order. In your case I think whatever has been set for acpi_video1 will override the acpi_video0 setting.

The brightness hotkeys probably only change acpi_video0 (please confirm!). I'm not sure if the keys get routed through userspace on your machine or not (Aaron can check), and I'm also not sure what the userspace does (or should do) given multiple acpi backlight interfaces.

In any case acpi_video0 and intel_backlight seem to work, and more or less in sync, so not our bug. Reassigning to ACPI video.
Comment 5 Aaron Lu 2014-06-11 03:27:02 UTC
(In reply to Jani Nikula from comment #4)
> On resume, ACPI video driver restores the backlight brightness on all
> devices that have a backlight interface, in order. In your case I think
> whatever has been set for acpi_video1 will override the acpi_video0 setting.

I agree.

> 
> The brightness hotkeys probably only change acpi_video0 (please confirm!).
> I'm not sure if the keys get routed through userspace on your machine or not

That would require the acpidump to be attached:
# acpidump > acpidump.txt

Also, the /sys/module/video/parameters/brightness_switch_enabled parameter may play a role. Please disable it:
# echo 0 > /sys/module/video/parameters/brightness_switch_enabled
BTW, this param's value will be 0 by default in v3.15.

> (Aaron can check), and I'm also not sure what the userspace does (or should
> do) given multiple acpi backlight interfaces.

The xorg driver will only pick one interface as the control interface for backlight and user space will rely on xorg driver so I think only one interface is used and it is acpi_video0.

> 
> In any case acpi_video0 and intel_backlight seem to work, and more or less
> in sync, so not our bug. Reassigning to ACPI video.

Agree.
The problem is the firmware made the two ACPI interfaces both work that caused problems. The driver did its job: restore the backlight level to what it is set previously. And the acpi_video1 is the latter one, so its brightness level gets restored later and becoming the end result. By default, we will set the brightness level to full during boot so that's why you get a full backlight level on resume if you didn't do any echo to acpi_video1.

The acpi video interface is different in that only it does the backlight level restore. I wonder perhaps we shouldn't do that either, but then I guess people who rely on this feature will complain regressions since the user space tool hasn't caught up yet.

For now, maybe use a pre-suspend/post-resume script to save/restore backlight level. I just googled and think the following may work:
# cat >/etc/pm/sleep.d/66-backlight
#!/bin/bash
case $1 in
    resume)
        cat /sys/class/backlight/acpi_video0/brightness > /sys/class/backlight/acpi_video1/brightness
    ;;
esac

I haven't tested it, please give it a try. I'm looking here:
https://wiki.archlinux.org/index.php/pm-utils

Note You need to log in before you can comment on or make changes to this bug.