brightness control not work with OLED panel

Bug #1831587 reported by Alex Tu
64
This bug affects 10 people
Affects Status Importance Assigned to Milestone
HWE Next
Fix Released
Undecided
Unassigned
OEM Priority Project
Fix Released
Undecided
Alex Tu
linux (Ubuntu)
Fix Released
High
Unassigned

Bug Description

image: disco 19.04
kernel: 5.0.0-15-generic
also verified failed on linux-image-unsigned-5.2.0-050200rc2-generic

also refer to :
 - https://askubuntu.com/questions/824949/lenovo-thinkpad-x1-yoga-oled-brightness
 - https://bugs.freedesktop.org/show_bug.cgi?id=97883

Linux can not control the brightness on the OLED panel in the traditional way [1].
Although there's a workaround from the community [2] that to execute script while brightness hotkey event is triggered. But if we want to upstream it, it's still a problem to recognize the OLED panel so that the system knows when to go workaround.
 - EDID of my laptop which has OLED: https://paste.ubuntu.com/p/w7rVqJTYDy/
 - EDID of the same model without OLED: https://paste.ubuntu.com/p/P3ChhX9yBJ/

there's a kernel patch related OLED for reference:
 - https://patchwork.kernel.org/patch/6133471/

[1] https://wiki.ubuntu.com/Kernel/Debugging/Backlight
[2] https://askubuntu.com/questions/824949/lenovo-thinkpad-x1-yoga-oled-brightness

Alex Tu (alextu)
Changed in oem-priority:
assignee: nobody → Alex Tu (alextu)
Revision history for this message
Ubuntu Kernel Bot (ubuntu-kernel-bot) wrote : Missing required logs.

This bug is missing log files that will aid in diagnosing the problem. While running an Ubuntu kernel (not a mainline or third-party kernel) please enter the following command in a terminal window:

apport-collect 1831587

and then change the status of the bug to 'Confirmed'.

If, due to the nature of the issue you have encountered, you are unable to run this command, please add a comment stating that fact and change the bug status to 'Confirmed'.

This change has been made by an automated script, maintained by the Ubuntu Kernel Team.

Changed in linux (Ubuntu):
status: New → Incomplete
Alex Tu (alextu)
tags: added: originate-from-1829985
Changed in linux (Ubuntu):
assignee: nobody → Kai-Heng Feng (kaihengfeng)
Changed in linux (Ubuntu):
importance: Undecided → High
status: Incomplete → Triaged
tags: added: somerville
Brad Figg (brad-figg)
tags: added: cscc
Changed in linux (Ubuntu):
assignee: Kai-Heng Feng (kaihengfeng) → nobody
Revision history for this message
Nicolas (nicolas-hoeft) wrote :

Same issue for me on an ThinkPad X1 extreme (gen 2),

EDID info:

# edid-decode /sys/class/drm/card0-eDP-1/edid [09:29:37]
Extracted contents:
header: 00 ff ff ff ff ff ff 00
serial number: 4c 83 41 41 00 00 00 00 13 1d
version: 01 04
basic params: b5 22 13 78 02
chroma info: 94 91 ae 51 3e b7 24 0b 50 54
established: 00 00 00
standard: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
descriptor 1: f0 d4 00 40 f1 70 18 80 30 20 44 00 58 c2 10 00 00 1b
descriptor 2: f0 d4 00 40 f1 70 18 80 30 20 44 00 58 c2 10 00 00 1b
descriptor 3: 00 00 00 0f 00 ff 09 3c ff 09 3c 2c 80 00 00 00 00 00
descriptor 4: 00 00 00 fe 00 41 54 4e 41 35 36 57 52 30 38 2d 30 20
extensions: 01
checksum: 15

Manufacturer: SDC Model 4141 Serial Number 0
Made week 19 of 2019
EDID version: 1.4
Digital display
10 bits per primary color channel
DisplayPort interface
Maximum image size: 34 cm x 19 cm
Gamma: 2.20
Supported color formats: RGB 4:4:4
First detailed timing is preferred timing
Established timings supported:
Standard timings supported:
Detailed mode: Clock 545.120 MHz, 344 mm x 194 mm
               3840 3888 3920 4160 hborder 0
               2160 2164 2168 2184 vborder 0
               +hsync -vsync
Detailed mode: Clock 545.120 MHz, 344 mm x 194 mm
               3840 3888 3920 4160 hborder 0
               2160 2164 2168 2184 vborder 0
               +hsync -vsync
Manufacturer-specified data, tag 15
ASCII string: ATNA56WR08-0
Has 1 extension blocks
Checksum: 0x15 (valid)

CEA extension block
Extension version: 3
11 bytes of CEA data
  Extended tag: Colorimetry data block
    xvYCC601
    xvYCC709
    sYCC601
    AdobeYCC601
    AdobeRGB
    BT2020cYCC
    BT2020YCC
    BT2020RGB
  Extended tag: HDR static metadata data block
    Electro optical transfer functions:
      Traditional gamma - SDR luminance range
      Traditional gamma - HDR luminance range
      SMPTE ST2084
    Supported static metadata descriptors:
      Static metadata type 1
    Desired content max luminance: 115
    Desired content max frame-average luminance: 109
    Desired content min luminance: 7
0 native detailed modes
Checksum: 0xab (valid)

EDID block does NOT conform to EDID 1.3!
        Missing name descriptor
        Missing monitor ranges
        Detailed block string not properly terminated

Changed in linux (Ubuntu):
assignee: nobody → AaronMa (mapengyu)
assignee: AaronMa (mapengyu) → nobody
Revision history for this message
Anthony Wong (anthonywong) wrote :

Nicolas,

For your OLED issue on ThinkPad X1 extreme (gen 2), we are following up in bug 1844798.

Revision history for this message
rojer (rojer9) wrote :

Anthony, what about the following panel (used on OLED Dell XPS 15):

$ edid-decode /sys/class/drm/card0-eDP-1/edid
EDID version: 1.4
Manufacturer: SDC Model a029 Serial Number 0
Made in week 10 of 2019
Digital display
10 bits per primary color channel
DisplayPort interface
Maximum image size: 34 cm x 19 cm
Gamma: 2.20
Supported color formats: RGB 4:4:4
First detailed timing includes the native pixel format and preferred refresh rate
Display x,y Chromaticity:
  Red: 0.6845, 0.3125
  Green: 0.2431, 0.7070
  Blue: 0.1386, 0.0546
  White: 0.3125, 0.3291
Established timings supported:
Standard timings supported:
Detailed mode: Clock 573.410 MHz, 344 mm x 194 mm
               3840 3888 3920 4400 hborder 0
               2160 2164 2168 2172 vborder 0
               +hsync -vsync
               VertFreq: 60 Hz, HorFreq: 130320 Hz
Detailed mode: Clock 573.410 MHz, 344 mm x 194 mm
               3840 3888 3920 4400 hborder 0
               2160 2164 2168 2172 vborder 0
               +hsync -vsync
               VertFreq: 60 Hz, HorFreq: 130320 Hz
ASCII string: 0HHFM
Manufacturer-specified data, tag 0
Has 1 extension blocks
Checksum: 0xc0 (valid)

CTA extension block
Extension version: 3
11 bytes of CTA data
  Extended tag: Colorimetry data block
    BT2020RGB
  Extended tag: HDR static metadata data block
    Electro optical transfer functions:
      Traditional gamma - SDR luminance range
      SMPTE ST2084
    Supported static metadata descriptors:
      Static metadata type 1
    Desired content max luminance: 115 (603.666 cd/m^2)
    Desired content max frame-average luminance: 109 (530.095 cd/m^2)
    Desired content min luminance: 208 (4.016 cd/m^2)
0 native detailed modes
Checksum: 0xe2 (valid)

Revision history for this message
Adam Dyess (addyess) wrote :

There does appear to be a work around here:

https://wiki.archlinux.org/index.php/HP_Spectre_x360_13-4231ng#Brightness_/_backlight

It requires bc and inotify-tools.

The workaround is for a long running program to listen for changes to /sys/class/backlight/intel_backlight

calculate the right luminance value

write them to xrandr.

Here's a slight improvement to the suggested script:

#!/bin/bash
#-----------------------------------------------------------------
# /usr/local/bin/brightness
# be sure this file is executable
#-----------------------------------------------------------------

backlight_path=/sys/class/backlight/intel_backlight
device=`xrandr | grep -w connected | awk '{ print $1 }'`

luminance() {
    read -r level < "$backlight_path"/actual_brightness
    bc <<< "scale=10;$level/$max"
}

read -r max < "$backlight_path"/max_brightness
xrandr --output "$device" --brightness "$(luminance)"

inotifywait -me modify --format '' "$backlight_path"/actual_brightness | while read; do
    echo "$device" $(luminance)
    xrandr --output "$device" --brightness "$(luminance)"
done

Revision history for this message
Adam Dyess (addyess) wrote :

An even better script so that all connected displays have their brightness adjusted

#!/bin/bash
#-----------------------------------------------------------------
# /usr/local/bin/brightness
# be sure this file is executable
#-----------------------------------------------------------------

backlight_path=/sys/class/backlight/intel_backlight

luminance() {
    read -r level < "$backlight_path"/actual_brightness
    bc <<< "scale=10;$level/$max"
}

devices() {
    xrandr | grep -w connected | awk '{ print $1 }'
}

apply() {
    for device in $(devices)
    do
        echo "$device" "$1"
        xrandr --output "$device" --brightness "$1"
    done
}

read -r max < "$backlight_path"/max_brightness
apply "$(luminance)"

inotifywait -me modify --format '' "$backlight_path"/actual_brightness | while read; do
    apply "$(luminance)"
done

Revision history for this message
Egbert van der Wal (eggie) wrote :

Same here on a Dell XPS 7590 with OLED display, same as @rojer9 in #4.

The script above in #6 works, combine with the autostart .desktop file from Archlinux wiki. Any chance of this either becoming automated in the setup or having the relevant kernel modules adjusted to adjust the brightness correctly on OLED displays?

Revision history for this message
Kai-Heng Feng (kaihengfeng) wrote :

20.04 should fix this issue.

Revision history for this message
Anthony Wong (anthonywong) wrote :

@Adam, Egbert
What kernel version are you using? I'd expect 5.4 in Focal or Bionic should have already fixed this issue.

Changed in linux (Ubuntu):
status: Triaged → Incomplete
Rex Tsai (chihchun)
tags: added: oem-priority
Revision history for this message
A A (capncrunch46) wrote :

When using multiple monitors, and disconnecting and reconnecting them, I noticed that Ubuntu 20.04 likes to set the external monitor's brightness to 0.06, and the laptop's brightness to maximum. This is done without changing the file at (/sys/class/backlight/intel_backlight/actual_brightness).

I have modified the above script to work with multiple monitors, and to change the brightness whenever a discrepancy between the desired and actual brightnesses of all monitors is detected. The script assumes that the internal laptop monitor's brightness is the only one to be changed by brightness keys, and that the laptop's monitor is the first monitor listed in the command `xrandr --listmonitors`.

Please reply if you have any issues with this script, as I do want to improve this.

#!/bin/bash
#-----------------------------------------------------------------
# /usr/local/bin/brightness
# be sure this file is executable
#-----------------------------------------------------------------

# Define a function which finds luminance values in default Ubuntu
# location, converts into a factor of maximum brightness
# Get the max brightness for reference.
# Get it to 2 decimal places
backlight_path=/sys/class/backlight/intel_backlight
read -r max < "$backlight_path"/max_brightness
luminance() {
    read -r level < "$backlight_path"/actual_brightness
    printf "%.2f" $(bc <<< "scale=10;$level/$max")
}

# Set up infinite loop
while true
do
    # Get the current brightness levels from xrandr. Store in array
    mapfile \
        -t xrandrbrightness \
        < <(xrandr --verbose --current \
            | grep Brightness \
            | sed 's/.* //' \
            | xargs printf "%.2f\n")

    # Get list of monitors and store in array
    mapfile \
        -t monitors \
        < <(xrandr --listmonitors --current \
            | grep -v 'Monitors' \
            | awk '{print $4}')

    # If the current brightness for monitor 0 != the desired value +/-0.01
    if (( $(echo "${xrandrbrightness[0]} != $(luminance)" | bc -l) ))
    then
        # Set the brightness of the laptop monitor to the desired value
        echo "${monitors[0]} Current:${xrandrbrightness[0]} Desired:$(luminance)"
        xrandr --output "${monitors[0]}" --brightness "$(luminance)"
    fi

    # Go through the rest of the monitors in the list
    for (( i=1; i<${#monitors[@]}; i++ ))
    do

        # Change the brightness of external monitors to 1 if they aren't
        if (( $(echo "${xrandrbrightness[$i]} != 1.00" | bc -l) ))
        then
            echo "${monitors[$i]} Current:${xrandrbrightness[$i]}"
            xrandr --output "${monitors[$i]}" --brightness 1
        fi
    done

    # Check every 100ms
    sleep 0.1
done

Timo Aaltonen (tjaalton)
Changed in linux (Ubuntu):
status: Incomplete → Fix Released
Changed in oem-priority:
status: New → Fix Released
Changed in hwe-next:
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.