<div dir="ltr"><div dir="ltr">Sorry for the necro-bump, I hadnt seen this go by<br><br><div>My main concern with this proposal is the phasing out of /sys/class/backlight/.</div><div>Currently on the user(user, not userland) level its easier for me to just modify</div><div>the file and be done with it. xbacklight doesnt tell me when its failed,</div><div><span class="gmail-co4"></span>brightnessctl doesnt make assumptions about what device is what, and</div><div>other brightness setting applications ive seen are much worse than them.</div><div>Someone needs to create a userland application thats less inconvenient</div><div>than `echo`ing into /sys/class/backlight with a name that human beings can</div><div>actually remember before I stop using the sysfs, perhaps "setbrightness"</div><div>could be the binary's name? Also I dont think its wise to disable or make it</div><div>read only though Kconfig as older apps may depend on it, maybe add a</div><div>kernel param that disables the old interface so bigger distros can pressure</div><div>app makers into changing the interface? As a big draw for DDC/CI is that</div><div>many displays support it as a way to change brightness(even if you arent</div><div>doing anything special that would break the old interface) perhaps it could</div><div>be an early adopter to that kernel parameter?<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 7, 2022 at 10:39 AM Hans de Goede <<a href="mailto:hdegoede@redhat.com">hdegoede@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">As discussed already several times in the past:<br>
 <a href="https://www.x.org/wiki/Events/XDC2014/XDC2014GoedeBacklight/" rel="noreferrer" target="_blank">https://www.x.org/wiki/Events/XDC2014/XDC2014GoedeBacklight/</a><br>
 <a href="https://lore.kernel.org/all/4b17ba08-39f3-57dd-5aad-d37d844b02c6@linux.intel.com/" rel="noreferrer" target="_blank">https://lore.kernel.org/all/4b17ba08-39f3-57dd-5aad-d37d844b02c6@linux.intel.com/</a><br>
<br>
The current userspace API for brightness control offered by<br>
/sys/class/backlight devices has various issues, the biggest 2 being:<br>
<br>
1. There is no way to map the backlight device to a specific<br>
   display-output / panel (1)<br>
2. Controlling the brightness requires root-rights requiring<br>
   desktop-environments to use suid-root helpers for this.<br>
<br>
As already discussed on various conference's hallway tracks<br>
and as has been proposed on the dri-devel list once before (2),<br>
it seems that there is consensus that the best way to to solve these<br>
2 issues is to add support for controlling a video-output's brightness<br>
through properties on the drm_connector.<br>
<br>
This RFC outlines my plan to try and actually implement this,<br>
which has 3 phases:<br>
<br>
<br>
Phase 1: Stop registering multiple /sys/class/backlight devs for a single display<br>
=================================================================================<br>
<br>
On x86 there can be multiple firmware + direct-hw-access methods<br>
for controlling the backlight and in some cases the kernel registers<br>
multiple backlight-devices for a single internal laptop LCD panel:<br>
<br>
a) i915 and nouveau unconditionally register their "native" backlight dev<br>
   even on devices where /sys/class/backlight/acpi_video0 must be used<br>
   to control the backlight, relying on userspace to prefer the "firmware"<br>
   acpi_video0 device over "native" devices.<br>
b) amdgpu and nouveau rely on the acpi_video driver initializing before<br>
   them, which currently causes /sys/class/backlight/acpi_video0 to usually<br>
   show up and then they register their own native backlight driver after<br>
   which the drivers/acpi/video_detect.c code unregisters the acpi_video0<br>
   device. This means that userspace briefly sees 2 devices and the<br>
   disappearing of acpi_video0 after a brief time confuses the systemd<br>
   backlight level save/restore code, see e.g.:<br>
   <a href="https://bbs.archlinux.org/viewtopic.php?id=269920" rel="noreferrer" target="_blank">https://bbs.archlinux.org/viewtopic.php?id=269920</a><br>
<br>
I already have a pretty detailed plan to tackle this, which I will<br>
post in a separate RFC email. I plan to start working on this right<br>
away, as it will be good to have this fixed regardless.<br>
<br>
<br>
Phase 2: Add drm_connector properties mirroring the matching backlight device<br>
=============================================================================<br>
<br>
The plan is to add a drm_connector helper function, which optionally takes<br>
a pointer to the backlight device for the GPU's native backlight device,<br>
which will then mirror the backlight settings from the backlight device<br>
in a set of read/write brightness* properties on the connector.<br>
<br>
This function can then be called by GPU drivers for the drm_connector for<br>
the internal panel and it will then take care of everything. When there<br>
is no native GPU backlight device, or when it should not be used then<br>
(on x86) the helper will use the acpi_video_get_backlight_type() to<br>
determine which backlight-device should be used instead and it will find<br>
+ mirror that one.<br>
<br>
<br>
Phase 3: Deprecate /sys/class/backlight uAPI<br>
============================================<br>
<br>
Once most userspace has moved over to using the new drm_connector<br>
brightness props, a Kconfig option can be added to stop exporting<br>
the backlight-devices under /sys/class/backlight. The plan is to<br>
just disable the sysfs interface and keep the existing backlight-device<br>
internal kernel abstraction as is, since some abstraction for (non GPU<br>
native) backlight devices will be necessary regardless.<br>
<br>
An alternative to disabling the sysfs class entirely, would be<br>
to allow setting it to read-only through Kconfig.<br>
<br>
<br>
What scale to use for the drm_connector bl_brightness property?<br>
===============================================================<br>
<br>
The tricky part of this plan is phase 2 and then esp. defining what the<br>
new brightness properties will look like and how they will work.<br>
<br>
The biggest challenge here is to decide on a fixed scale for the main<br>
brightness property, say 0-65535, using scaling where the actual hw scale<br>
is different, or if this should simply be a 1:1 mirror of the current<br>
backlight interface, with the actual hw scale / brightness_max value<br>
exposed as a drm_connector property.<br>
<br>
1:1 advantages / 0-65535 disadvantages<br>
- Userspace will likely move over to the connector-props quite slowly and<br>
  we can expect various userspace bits, esp. also custom user scripts, to<br>
  keep using the old uAPI for a long time. Using the 2 APIs are intermixed<br>
  is fine when using a 1:1 brightness scale mapping. But if we end up doing<br>
  a scaling round-trip all the time then eventually the brightness is going<br>
  do drift. This can even happen if the user never changes the brightness<br>
  when userspace saves it over suspend/resume or reboots.<br>
- Almost all laptops have brightness up/down hotkeys. E.g GNOME decides<br>
  on a step size for the hotkeys by doing min(brightness_max/20, 1).<br>
  Some of the vendor specific backlight fw APIs (e.g. dell-laptop) have<br>
  only 8 steps. When giving userspace the actual max_brightness value, then<br>
  this will all work just fine. When hardcode brightness_max to 65535 OTOH<br>
  then in this case GNOME will still give the user 20 steps where only 1<br>
  in every 2-3 steps actually changes the brightness which IMHO is<br>
  an unacceptably bad user experience.<br>
<br>
0-65535 advantages / 1:1 disadvantages<br>
- Without a fixed scale for the brightness property the brightness_max<br>
  value may change after an userspace application's initial enumeration<br>
  of the drm_connector. This can happen when neither the native GPU nor<br>
  the acpi_video backlight devices are present/usable in this case<br>
  acpi_video_get_backlight_type() will _assume_ a vendor specific fw API<br>
  will be used for backlight control and the driver proving the "vendor"<br>
  backlight device will show up much later and may even never show-up,<br>
  so waiting for it is not an option. With a fixed 0-65535 scale userspace<br>
  can just always assume this and the drm_connector backlight props helper<br>
  code can even cache writes and send it to the actual backlight device<br>
  when it shows up. With a 1:1 mapping userspace needs to listen for<br>
  a uevent and then update the brightness range on such an event.<br>
<br>
I believe that the 1:1 mapping advantages out way the disadvantages<br>
here. Also note that current userspace already blindly assumes that<br>
all relevant drivers are loaded before the graphical-environment<br>
starts and all the desktop environments as such already only do<br>
a single scan of /sys/class/backlight when they start. So when<br>
userspace forgets to add code to listen for the uevent when switching<br>
to the new API nothing changes; and with the uevent userspace actually<br>
gets a good mechanism to detect backlight drivers loading after<br>
the graphical-environment has already started.<br>
<br>
So based on this here is my proposal for a set of new brightness<br>
properties on the drm_connector object. Note these are all prefixed with<br>
bl which stands for backlight, which is technically not correct for OLED.<br>
But we need a prefix to avoid a name collision with the "brightness"<br>
attribute which is part of the existing TV specific properties and IMHO<br>
it is good to have a common prefix to make it clear that these all<br>
belong together.<br>
<br>
<br>
The drm_connector brightness properties<br>
=======================================<br>
<br>
bl_brightness: rw 0-int32_max property controlling the brightness setting<br>
of the connected display. The actual maximum of this will be less then<br>
int32_max and is given in bl_brightness_max.<br>
<br>
bl_brightness_max: ro 0-int32_max property giving the actual maximum<br>
of the display's brightness setting. This will report 0 when brightness<br>
control is not available (yet).<br>
<br>
bl_brightness_0_is_min_brightness: ro, boolean<br>
When this is set to true then it is safe to set brightness to 0<br>
without worrying that this completely turns the backlight off causing<br>
the screen to become unreadable. When this is false setting brightness<br>
to 0 may turn the backlight off, but this is _not_ guaranteed.<br>
This will e.g. be true when directly driving a PWM and the video-BIOS<br>
has provided a minimum (non 0) duty-cycle below which the driver will<br>
never go.<br>
<br>
bl_brightness_control_method: ro, enum, possible values:<br>
none:     The GPU driver expects brightness control to be provided by another<br>
          driver and that driver has not loaded yet.<br>
unknown:  The underlying control mechanism is unknown.<br>
pwm:      The brightness property directly controls the duty-cycle of a PWM<br>
          output.<br>
firmware: The brightness is controlled through firmware calls.<br>
DDC/CI:   The brightness is controlled through the DDC/CI protocol.<br>
gmux:     The brightness is controlled by the GMUX.<br>
Note this enum may be extended in the future, so other values may<br>
be read, these should be treated as "unknown".<br>
<br>
When brightness control becomes available after being reported<br>
as not available before (bl_brightness_control_method=="none")<br>
a uevent with CONNECTOR=<connector-id> and<br>
PROPERTY=<bl_brightness_control_method-id> will be generated<br>
at this point all the properties must be re-read.<br>
<br>
When/once brightness control is available then all the read-only<br>
properties are fixed and will never change.<br>
<br>
Besides the "none" value for no driver having loaded yet,<br>
the different bl_brightness_control_method values are intended for<br>
(userspace) heuristics for such things as the brightness setting<br>
linearly controlling electrical power or setting perceived brightness.<br>
<br>
Regards,<br>
<br>
Hans<br>
<br>
<br>
1) The need to be able to map the backlight device to a specific display<br>
has become clear once more with the recent proposal to add DDCDI support:<br>
<a href="https://lore.kernel.org/lkml/20220403230850.2986-1-yusisamerican@gmail.com/" rel="noreferrer" target="_blank">https://lore.kernel.org/lkml/20220403230850.2986-1-yusisamerican@gmail.com/</a><br>
<br>
2) <a href="https://lore.kernel.org/all/4b17ba08-39f3-57dd-5aad-d37d844b02c6@linux.intel.com/" rel="noreferrer" target="_blank">https://lore.kernel.org/all/4b17ba08-39f3-57dd-5aad-d37d844b02c6@linux.intel.com/</a><br>
Note this proposal included a method for userspace to be able to tell the<br>
kernel if the native/acpi_video/vendor backlight device should be used,<br>
but this has been solved in the kernel for years now:<br>
 <a href="https://www.spinics.net/lists/linux-acpi/msg50526.html" rel="noreferrer" target="_blank">https://www.spinics.net/lists/linux-acpi/msg50526.html</a><br>
An initial implementation of this proposal is available here:<br>
 <a href="https://cgit.freedesktop.org/~mperes/linux/log/?h=backlight" rel="noreferrer" target="_blank">https://cgit.freedesktop.org/~mperes/linux/log/?h=backlight</a><br>
<br>
</blockquote></div></div>