Skip to content

About

Native OLED brightness and HDR for the 2026 Razer Blade 16 on Linux using a custom EDID overlay.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

 

History

14 Commits

Folders and files

Repository files navigation

🔆 Razer Blade 16 (2026)
OLED brightness + HDR on Linux

Native brightness control and full HDR (1107 nits) for the Razer Blade 16 (2026) OLED on Linux.
A custom EDID firmware overlay re-encodes the panel's HDR/colorimetry data into the CTA-861 block the kernel actually reads - no daemon, no ICC workaround, no patches.
KDE Plasma 6 · Wayland · Intel Xe + NVIDIA · Samsung ATNA60HU06-0

Platform: Linux KDE Plasma 6 / Wayland Razer Blade 16 (2026) Samsung ATNA60HU06 OLED License: MIT


Quick Fix

Run this single command:

bash <(curl -fsSL https://raw.githubusercontent.com/visorcraft/razer_16_2026_linux_oled_brightness/master/quick-fix.sh)

This targets the CachyOS + Limine setup documented here.

It installs the EDID overlay, updates Limine and the initramfs, applies the 120Hz mode, and finishes HDR, WCG, and OLED brightness setup after one reboot.

Overview

Working setup for native brightness control AND full HDR (1107 nits peak) on the Samsung ATNA60HU06-0 16" 240Hz OLED panel that ships in the Razer Blade 16 (2026, model RZ09-0581) on Linux + KDE Plasma 6 / Wayland.

TL;DR: Provide a custom EDID firmware overlay that re-encodes the panel's HDR/colorimetry data into a CTA-861 Extension Block (the format the kernel DRM parser actually reads). Once the kernel marks the connector as HDR-capable, KWin's native software brightness AND HDR mode both unlock. No daemon, no ICC profile workaround, no patches to upstream code.

This was tested on:

  • CachyOS rolling, kernel 7.0.5-cachyos and 7.1.0-rc2-cachyos-rc
  • KDE Plasma 6.6.4 / KWin 6.6.4 / Wayland
  • linux-cachyos-nvidia-open (nvidia open kernel modules, driver 595.71.05)
  • Razer Blade 16 (2026) RZ09-0581 with BIOS 2.01

It will likely work on any distro using a recent kernel + KDE Plasma 6.6+ and the same panel. AMD Ryzen variants of the Razer Blade 16 (2025/2026) likely have the same panel and should benefit identically - kernel parameter form is independent of GPU vendor.


Important caveat: cap the panel to 120Hz on Intel Xe (Panther Lake)

Symptom: at the panel's native 240Hz under KWin Wayland, the Intel xe driver cannot retire KMS atomic commits fast enough. KWin floods the journal with atomic commit failed: Device or resource busy (~8–13/min), the kernel periodically logs:

xe 0000:00:02.0: [drm:drm_atomic_helper_setup_commit] [PLANE:64:plane 2A] busy with a previous commit

and after enough accumulated EBUSY pressure the GPU engine resets:

xe 0000:00:02.0: [drm] Tile0: GT0: Engine reset: engine_class=rcs, ... in kwin_wayland
xe 0000:00:02.0: [drm] Xe device coredump has been created

The display "glitches" from that point and the system hard-freezes within ~10–60 minutes. Reproduced reliably on Razer Blade 16 (2026, RZ09-0581) with kernels linux-cachyos 7.0.8 and linux-cachyos-rc 7.1.0-rc3 - same rate on both, so this is not RC-specific. The 120Hz fix below also works identically on both kernels (verified by A/B-testing each rate on each kernel).

Diagnosis: the xe driver's per-commit latency exceeds the 4.17 ms 240Hz vsync interval but fits within the 8.33 ms 120Hz interval. It's a driver throughput ceiling specific to Panther Lake-era xe code, not a feature/EDID issue - HDR, Wide Color Gamut, EDID overlay, and the brightness slider are all innocent and can stay enabled.

Fix: add and select a custom 120Hz mode. The panel's EDID exposes only 240Hz and 60Hz natively (no 120Hz), but the panel itself accepts a 120Hz timing fine.

# add custom 2560x1600@120Hz mode (CVT reduced blanking)
kscreen-doctor output.eDP-1.addCustomMode.2560.1600.120000.reduced

# list modes to find the new index - it gets appended at the end
kscreen-doctor --outputs

# select it (replace 23 with whatever index the previous command shows)
kscreen-doctor output.eDP-1.mode.23

Or run the idempotent installer from this repository:

./install-120hz-mode.sh

Pass a different connector name as the first argument if needed. The script adds the custom mode only when missing, then selects it.

KWin persists this in ~/.config/kwinoutputconfig.json as mode.refreshRate: 119963. Survives reboot.

Why 60Hz didn't work either: counter-intuitively, the panel's native 60Hz mode also produces atomic-commit failures at roughly the same rate as 240Hz. Best guess is that KWin renders animations / cursor / plane updates at a logical rate that happens to align cleanly with 120Hz but not 60Hz on this panel. The 120Hz custom mode is the only setting that drops failures to ~0.

Verify:

journalctl --since "5 minutes ago" --no-pager | grep -c "atomic commit failed: Device or resource busy"
# 0–2 in 5 min = fine. Sustained ≥5/min = throughput is racing again.

To capture the kernel-side fingerprint yourself:

sudo sh -c 'echo 0x1e > /sys/module/drm/parameters/debug'
# reproduce; watch journalctl for "busy with a previous commit"
sudo sh -c 'echo 0 > /sys/module/drm/parameters/debug'

This caveat is independent of the EDID overlay below - you'll hit it whether or not you apply the brightness/HDR fix, as long as you're on Panther Lake + xe + KWin Wayland at 240Hz. The EDID overlay is purely additive metadata; it doesn't affect commit-path performance.

Status: filed as a xe-driver throughput limitation. May be resolved by newer kernels - worth re-testing 240Hz every few minor kernel bumps. Tracking commits touching drm_atomic_helper, fence retirement, or plane completion in the xe driver subdirectory.

Residual failures even at 120Hz: intel_lpmd

If you have intel_lpmd (Intel Low Power Mode Daemon) installed and active - default on CachyOS and several other distros for Panther Lake - you'll still see ~0.5 atomic-commit-failed events per minute even after the 120Hz fix. The events correlate 1:1 with intel_lpmd workload-type transitions:

intel_lpmd[...]: [ Enter] [   AUTO] [ UTIL_IDLE_BURSTY ]: WLT [ 3] CPUMASK [8] ...
kwin_wayland[...]: atomic commit failed: Device or resource busy

intel_lpmd dynamically gates CPU clusters (P-cores vs E-cores vs LPE-cores) based on detected workload. Each transition causes a brief iGPU clock stall, during which KWin's next atomic commit lands while a previous one is still pending -> single EBUSY -> recovered on the next vsync.

These residual failures are harmless - single-event, self-recovering, never accumulate fence pressure. They don't lead to engine resets. But to eliminate them entirely (cosmetic log silence + a tiny iGPU clock-stability gain) you can either:

# Quick test - stop it for the current session:
sudo systemctl stop intel_lpmd.service

# Permanent - disable so it doesn't start at boot:
sudo systemctl disable --now intel_lpmd.service

Tradeoff: intel_lpmd does provide measurable battery savings under light workloads. A reasonable middle ground is to keep it enabled but stop/start it automatically based on AC/battery state via a small udev-driven systemd service.


Symptoms before the fix

  • Brightness slider in System Settings does nothing.
  • Fn+F8 / Fn+F9 brightness keys do nothing.
  • Direct sudo sh -c 'echo X > /sys/class/backlight/intel_backlight/brightness' (and same for nvidia_0, nvidia_wmi_ec_backlight, acpi_video0/1) all succeed at the sysfs level but the panel doesn't actually dim.
  • kscreen-doctor --outputs reports HDR: incapable and Wide Color Gamut: incapable.
  • Setting kscreen-doctor output.eDP-1.brightness.N stores the value but doesn't change the panel.

Root cause

This is an OLED panel - there is literally no LED backlight to control. "Dimming" on OLED has to be done by scaling pixel intensity in the compositor.

KWin (Plasma 6.6) supports software pixel-level brightness on OLED (allowSdrSoftwareBrightness), but gates it on the connector being HDR-capable. KWin checks for HDR-capable by looking at the kernel's parsed EDID - specifically the CTA-861 HDR Static Metadata Block + a CTA-861 Colorimetry Data Block.

Samsung put both pieces of information in the panel's EDID, but in a DisplayID v2.0 Extension Block rather than the older CTA-861 format. The Linux DRM HDR parser doesn't read DisplayID v2.0 HDR data (as of kernel 7.x). So the kernel reports the connector as non-HDR, KWin agrees, software brightness stays off, HDR stays off, panel feels broken.

The fix is to provide an EDID firmware override that adds a CTA-861 Extension Block carrying the same data that's already in the DisplayID block.


How to apply (full guide)

Run as root where shown. Replace any kernel-cmdline / bootloader commands with the equivalent for your bootloader (this guide shows systemd-boot, GRUB, and Limine variants).

1. Build a custom EDID

Clone this repo (or just download build-oled-hdr-edid.py), then:

python3 build-oled-hdr-edid.py
# writes /tmp/oled-hdr.bin

The script reads /sys/class/drm/card0-eDP-1/edid (the panel's stock EDID), strips any existing CTA-861 extensions, and adds one carrying:

  • Colorimetry Data Block declaring BT.2020 RGB / YCC / cYCC and DCI-P3 RGB D65 (extended tag 0x05).
  • HDR Static Metadata Data Block declaring PQ (SMPTE ST 2084) EOTF, static metadata type 1, ~1107 nits content max luminance, ~497 nits frame-average max, and 0.044 nits min (extended tag 0x06).

Verify the result:

edid-decode /tmp/oled-hdr.bin | grep -A8 'CTA-861 Extension'

You should see both blocks listed cleanly.

2. Install the EDID firmware

sudo mkdir -p /lib/firmware/edid
sudo install -m 0644 /tmp/oled-hdr.bin /lib/firmware/edid/oled-hdr.bin

3. Bundle the EDID into the initramfs

The Intel xe (or i915) display driver loads early in boot, before the root filesystem is mounted, so the firmware file must live inside the initramfs.

For mkinitcpio (Arch / CachyOS / EndeavourOS / Manjaro):

# add to FILES=()
sudo sed -i 's|^FILES=()|FILES=(/lib/firmware/edid/oled-hdr.bin)|' /etc/mkinitcpio.conf
# (or edit the file by hand if FILES=() isn't on a line by itself)

sudo mkinitcpio -P

For dracut (Fedora / openSUSE / RHEL):

sudo tee /etc/dracut.conf.d/oled-hdr.conf <<'EOF'
install_items+=" /lib/firmware/edid/oled-hdr.bin "
EOF
sudo dracut --regenerate-all --force

For Debian / Ubuntu (initramfs-tools):

echo /lib/firmware/edid/oled-hdr.bin | sudo tee -a /etc/initramfs-tools/conf.d/oled-hdr-firmware
sudo update-initramfs -u -k all

4. Add the kernel command-line parameter

Add drm.edid_firmware=eDP-1:edid/oled-hdr.bin to your kernel cmdline.

The DRM module is built into the kernel on most modern distros, so the parameter prefix is drm. rather than drm_kms_helper. (which was the old name; it errors silently). Verify on your system with: ls /sys/module/drm/parameters/edid_firmware

For systemd-boot:

Edit /boot/loader/entries/<your-entry>.conf and append to the options line.

For GRUB:

Edit /etc/default/grub, append the param to GRUB_CMDLINE_LINUX_DEFAULT, then:

sudo grub-mkconfig -o /boot/grub/grub.cfg

For Limine (CachyOS default):

Edit /etc/default/limine, append the param inside the KERNEL_CMDLINE[default] quotes, then:

sudo limine-update

5. Reboot

sudo reboot

6. Verify the fix took effect

After login, run:

sudo dmesg | grep -i 'edid'

You should NOT see Requesting EDID firmware ... failed (err=-2). If you do, the firmware file isn't in the initramfs - repeat step 3.

kscreen-doctor --outputs | grep -E 'HDR|Wide Color|Peak|SDR|Color resolution'

You should see:

HDR: enabled  (or "disabled", which means capable but currently off)
  ...
  Peak brightness: 1107 nits
Wide Color Gamut: enabled (or disabled)

If HDR shows disabled (not incapable), KWin recognized the panel - enable HDR + WCG with:

kscreen-doctor output.eDP-1.hdr.enable output.eDP-1.wcg.enable

(or via System Settings → Display & Monitor → eDP-1 → toggles)

7. Tune SDR brightness reference

The sdrBrightness value in nits is what KWin treats as "100% on the brightness slider" for non-HDR content. Default is usually 200, which feels dim on this panel. Try:

# Comfortable indoor:
kscreen-doctor output.eDP-1.sdr-brightness.500

# Sun-readable, slider-100% feels like outdoor brightness:
kscreen-doctor output.eDP-1.sdr-brightness.1100

This panel happily takes 1100 even though kscreen-doctor documents the range as 100..1000. Caveat: don't camp at >900 nits sustained on always-bright UI elements - OLED burn-in risk. Daily-use slider position of ~25% of a 1100-nit reference (= ~275 nits) is comfortable indoors.


Verifying everything is healthy

# Kernel actually loaded our EDID firmware (no err=-2):
sudo dmesg | grep -i edid

# EDID is in the initramfs (mkinitcpio example; adjust for your tools):
sudo lsinitcpio /boot/initramfs-linux*.img | grep edid

# KWin sees HDR as capable:
kscreen-doctor --outputs | grep -E 'HDR|Wide Color|Peak'

# Brightness slider works (test by pressing Fn+F8/F9 or moving the slider).

If HDR: enabled regresses to incapable after a kernel update, re-check that your initramfs builder still includes the firmware file (some distro upgrades reset config files).


NVIDIA driver state (verified working)

For the dGPU half of the hybrid setup - confirmed healthy on 2026-05-11:

  • Driver: 595.71.05 (open kernel modules via linux-cachyos-nvidia-open)
  • GPU: RTX 5080 Mobile at PCI 01:00.0, nvidia kernel driver bound, 16 GB VRAM, idle ~33 °C / 19 W
  • Modules loaded: nvidia, nvidia_drm, nvidia_modeset, nvidia_uvm, nvidia_wmi_ec_backlight
  • PRIME render offload: working - default rendering stays on the Intel Panther Lake iGPU (xe driver); prime-run <app> (or __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia <app>) routes GL to the RTX 5080, confirmed via glxinfo reporting OpenGL renderer string: NVIDIA GeForce RTX 5080 Laptop GPU.

Quick checks to re-verify after kernel/driver updates:

nvidia-smi                 # driver loaded, GPU visible
lsmod | grep -i nvidia     # modules present
lspci -k | grep -A3 -i nvidia   # kernel driver bound to the dGPU
prime-run glxinfo | grep -i 'OpenGL renderer'   # offload reaches the dGPU

The nvidia_wmi_ec_backlight module loads on this laptop but does not actually drive panel brightness - see the OLED note above; the panel has no backlight to control.


Uninstall (revert to stock)

# Remove EDID firmware
sudo rm /lib/firmware/edid/oled-hdr.bin

# Remove kernel cmdline parameter (depends on bootloader; reverse step 4)

# Remove from initramfs (mkinitcpio)
sudo sed -i 's|FILES=(/lib/firmware/edid/oled-hdr.bin)|FILES=()|' /etc/mkinitcpio.conf
sudo mkinitcpio -P

# Reboot
sudo reboot

You'll lose HDR and the brightness slider will go back to being non-functional unless you set up the ICC fallback (see icc-fallback/ in this repo).


What if the EDID overlay doesn't unlock HDR on my distro?

Some compositors don't recognize HDR even with proper CTA-861 metadata (they may want additional EDID extensions, or have different gates). In that case the EDID overlay won't help and you're stuck with software brightness only. The icc-fallback/ directory in this repo contains a userspace daemon that simulates dimming on OLED via dynamically-applied dim ICC profiles, intercepting KDE PowerDevil brightness DBus signals. It works on Plasma 6 even when HDR remains off. See icc-fallback/README.md.


How this was figured out

Long version is in the linked sources - short version:

  1. Initially looked like a "wrong backlight device" issue (the laptop has four phantom /sys/class/backlight/* entries - intel_backlight, nvidia_0, nvidia_wmi_ec_backlight, acpi_video* - and they all accept writes silently). Wasted time trying every standard kernel parameter (acpi_backlight=video|native|vendor|nvidia_wmi_ec, xe.enable_dpcd_backlight=0).
  2. The Arch Wiki Backlight page has a single sentence note: "OLED screens have no backlight." That was the unlock - the entire sysfs backlight subsystem is irrelevant on this panel. Dimming has to come from the compositor.
  3. Built an ICC-profile-based daemon as a workaround that dimmed via KWin's color management pipeline. Worked, but capped at SDR ~400 nits and felt like a kludge.
  4. Investigated WHY KWin reported HDR: incapable despite the panel being spec'd as ~1100 nits HDR. edid-decode showed the kernel was reading the panel's EDID fine - the HDR/colorimetry data was simply in a DisplayID v2.0 Extension Block that the kernel's CTA-861 HDR parser doesn't look at.
  5. Built a custom EDID firmware overlay re-encoding the same data into a CTA-861 block. After the third reboot iteration (wrong module-name prefix, then forgot to add to initramfs, then missing the Colorimetry Data Block), HDR: incapable finally flipped to HDR: enabled → software brightness unlocked too → ICC daemon retired.

Credits / related work


License

Licensed under the MIT License - see LICENSE for the full text.

© 2026 VisorCraft LLC. Provided as-is, without warranty of any kind. The EDID overlay, kernel command-line parameters, and sysfs / systemctl commands here modify low-level display and boot configuration - use them at your own risk.

About

Native OLED brightness and HDR for the 2026 Razer Blade 16 on Linux using a custom EDID overlay.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages