johnfanv2 / LenovoLegionLinux

Driver and tools for controlling Lenovo Legion laptops in Linux including fan control and power mode.
https://github.com/johnfanv2/LenovoLegionLinux
GNU General Public License v2.0
1.64k stars 61 forks source link
arch-linux archlinux battery charging conservation-mode debian fan-control gaming gentoo laptop legion lenovo lenovo-ideapad lenovo-legion lenovo-vantage linux linux-driver powermode ubuntu utility

LenovoLegionLinux Lenovo Legion Linux Support

Build Join Discord Check Reddit More Reddit
Unbutu and Debian PPA Fedora Copr AUR AUR DKMS GURU Overlay LLL Package NixOS
Nobara PikaOS

Other language versions of this README file:


This project is not affiliated with Lenovo in any way

Lenovo Legion Linux (LLL) brings additional drivers and tools for Lenovo Legion series laptops to Linux. It is the alternative to Lenovo Vantage or Legion Zone (both Windows only).

It allows you to control features like the fan curve, power mode, power limits, rapid charging, and more. This has been achieved through reverse engineering and disassembling the ACPI firmware, as well as the firmware and memory of the embedded controller (EC).

:star: Please star this repository if this is useful or might be useful in the future.

:star2: My goal is to merge the driver into the main Linux kernel so it comes automatically with Linux and no recompilation is required after a Linux update

:boom: Starring shows that this is useful to me and the Linux community so hopefully a merge into the Kernel is possible.

:rocket: Features

fancurve psensor powermode

:mega: Overview

:package: Available Packages

[^1]: Build with latest commit every day at midnight GMT

:pushpin: Confirmed Compatible Models

If you have a 2022 or 2023 model, please help testing the new features here.

If you have a light in the lid (Y-logo) or at the IO-ports (all Legion 7), please help testing controlling it here.

Other Lenovo Legion models from 2020 to 2023 probably also work. The following models were confirmed. If you have a model with a BIOS version with the same leading letters, e.g. EFCN (like EFCN54WW) then it will probably work. If you want to confirm that your model works or if it does not work, please raise a issue.

Note: Features that are not confirmed probably also work. They were just not tested.

Currently fan control is not working for the following models. Other features, probably work:

:warning: Disclaimer

:bulb: Instructions

Please do the following:

Requirements

You will need to install the following to download and build it. If there is an error of any package, find the alternative name in your distribution and install them.

Ubuntu/Debian/Pop!_OS/Mint/elementary OS/Zorin

sudo apt-get update
sudo apt-get install -y make gcc linux-headers-$(uname -r) build-essential git lm-sensors wget python3-pyqt6 python3-yaml python3-venv python3-pip python3-argcomplete python3-darkdetect
# Install the following for installation with DKMS
sudo apt-get install dkms openssl mokutil

RHEL/CentOS/RockyLinux/Fedora/AlmaLinux

sudo dnf install -y kernel-headers kernel-devel dmidecode lm_sensors python3-PyQt6 python3-yaml python3-pip python3-argcomplete python3-darkdetect
sudo dnf groupinstall "Development Tools"
sudo dnf group install "C Development Tools and Libraries"
# Install the following for installation with DKMS
sudo dnf install dkms openssl mokutil

Alternatively, you might use yum instead of dnf and start with sudo yum update. Installing "C Development Tools and Libraries" might not be needed depending of your distribution.

openSUSE

sudo zypper install make gcc kernel-devel kernel-default-devel git libopenssl-devel sensors dmidecode python3-qt5 python3-pip python3-PyYAML python3-argcomplete python3-darkdetect
# Install the following for installation with DKMS
sudo zypper install dkms openssl mokutil

Note: Check for the correct Header package.

Arch/Manjaro/EndeavourOS

sudo pacman -S linux-headers base-devel lm_sensors git dmidecode python-pyqt6 python-yaml python-argcomplete python-darkdetect
# Install the following for installation with DKMS
sudo pacman -S dkms openssl mokutil

Note: Check for the correct Header package.

Troubleshooting:

sudo apt install --reinstall linux-headers-$(uname -r)

Build and Test Instruction

git clone https://github.com/johnfanv2/LenovoLegionLinux.git
cd LenovoLegionLinux/kernel_module
make
sudo make reloadmodule

For further instructions, problems, and tests see Initial Usage Testing below. Do them first before a permanent installation.

Expected result:

Unexpected result:

make[1]: *** /lib/modules/6.2.9-arch1-1/build: No such file or directory.  Stop.
make[1]: Leaving directory '/home/user/LenovoLegionLinux/kernel_module'
make: *** [Makefile:13: all] Error 2

Permanent Install Instruction

After successfully building and testing (see below), run from the folder LenovoLegionLinux/kernel_module

make
sudo make install

You must recompile and reinstall it again with above commands after each kernel update, as usual for external kernel modules. I want to get it merged into the mainline Linux kernel, so this is not needed anymore. So please star this repository :)

Uninstall Instruction

Go to the folder LenovoLegionLinux/kernel_module

make
sudo make uninstall

Installing via DKMS

DKMS is a utility that eliminates the need to manually rebuild and reinstall the driver after every kernel update. DKMS will do the reinstallation automatically.

You must first install the package to with DKMS. See Requirements section.

sudo mkdir -p /usr/src/LenovoLegionLinux-1.0.0
sudo cp ./kernel_module/* /usr/src/LenovoLegionLinux-1.0.0 -r
sudo dkms add -m LenovoLegionLinux -v 1.0.0
sudo dkms build -m LenovoLegionLinux -v 1.0.0

Or via makefile

cd kernel_module
sudo make dkms # Don't forget to run as root

Secure boot

If you want the driver to work with secure boot, then follow the steps described here https://github.com/dell/dkms#secure-boot or here https://wiki.archlinux.org/title/User:Krin/Secure_Boot,_full_disk_encryption,_and_TPM2_unlocking_install#Secure_boot. Note that this is a little more advanced. For initial testing, just load the module as described in the steps above or disable secure boot.

Uninstalling via DKMS

sudo dkms remove -m LenovoLegionLinux -v 1.0.0
reboot

Permanently Patching the Kernel

This is only useful for advanced users that build there own kernel. A automatically generated patch is provided on the release page whenver a stable milestone has been reached: Releases

:octocat: Initial Usage Testing

Please note:

Quick Test: Module is properly loaded

# After you have run from folder LenovoLegionLinux/kernel_module (for non DKMS)
sudo make reloadmodule 

# Check the kernel log
sudo dmesg

Expected result:

Unexpected result:

[126675.495983] legion PNP0C09:00: Module not usable for this laptop because it is not in allowlist. Notify maintainer if you want to add your device or force load with param force.
[126675.495984] legion PNP0C09:00: legion_laptop not loaded for this device
[126675.496014] legion: probe of PNP0C09:00 failed with error -12

Quick Test: Reading Current Fancurve from Hardware

# Read the current fancurve and other debug output
sudo cat /sys/kernel/debug/legion/fancurve

Expected output:

Example:

EC Chip ID: 8227 
EC Chip Version: 2a4 
fan curve current point id: 0 
fan curve points size: 8 
Current fan curve in UEFI
rpm1|rpm2|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
0 0 2 2 0 48 0 59 0 41
1700 1900 2 2 45 54 55 59 39 44
1900 2000 2 2 51 58 55 59 42 50
2200 2100 2 2 55 62 55 59 46 127
2300 2400 2 2 59 71 55 59 127 127
2600 2700 2 2 68 76 55 64 127 127
2900 3000 2 2 72 81 60 68 127 127
3500 3500 2 2 78 127 65 127 127 127

The fan curve is displayed as a table with the following columns:

rpm1: speed in rpm for fan1 at this point
rpm2: speed in rpm for fan1 at this point
acceleration: acceleration time (higher = slower)
deceleration: deceleration time (higher = slower)
cpu_min_temp: CPU temperature must go below this before leaving this point
cpu_max_temp: if CPU temperature is above this value, go to next point 
gpu_min_temp: GPU temp must go below this before leaving this level
gpu_max_temp: if GPU temperature is above this value, go to next point 
ic_min_temp: IC temp must go below this before leaving this level
ic_max_temp: if IC temperature above this value, go to next point 

All temperatures are in degree Celsius.

Note: This is just a debug output. The fan curve is configured as usual using the standard hwmon interface.

Unexpected:

Quick Test: Read Sensor Values from Hardware

# Run the command sensors
sensors

Expected output:

Unexpected output:

Quick Test: Change Current Fan Curve from Hardware with hwmon

# Change the RPM of fans at the second and third point of the fan curve to 1500 rpm, 1600 rpm, 1700 rpm, 1800 rpm.
# Get root
sudo su
# As root enter
# 2. point, 1. fan
echo 1500 > /sys/module/legion_laptop/drivers/platform:legion/PNP0C09:00/hwmon/hwmon*/pwm1_auto_point2_pwm
# 2. point, 2.fan
echo 1600 > /sys/module/legion_laptop/drivers/platform:legion/PNP0C09:00/hwmon/hwmon*/pwm2_auto_point2_pwm
# 3. point, 1. fan
echo 1700 > /sys/module/legion_laptop/drivers/platform:legion/PNP0C09:00/hwmon/hwmon*/pwm1_auto_point3_pwm
# 3. point, 2.fan
echo 1800 > /sys/module/legion_laptop/drivers/platform:legion/PNP0C09:00/hwmon/hwmon*/pwm2_auto_point3_pwm

# Read the current fancurve and check if changes were made
cat /sys/kernel/debug/legion/fancurve

Expected:

rpm1|rpm2|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp
XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
1500 1600 XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
1700 1800 XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX

If you want to reset your fan curve, just toggle with Ctrl+Q or Fn+Q the power mode or restart and everything is gone.

Unexpected:

Quick Test: Set your custom fan curve

Set a custom fan curve with the provided script. See Creating and Setting your own Fan Curve below.

Test: Finish

:computer: Normal Usage

you have to install the kernel module permanently (see above), otherwise you must reload it manually after each restart

Temperature and Fan Monitoring

The temperatures and fan speeds should be displayed in any graphical tool that monitors them, e.g. psensor. You have to install it first before running:

psensor

psensor

Changing and Setting your own Fan Curve with the Python GUI

Start the GUI as root

# run from folder LenovoLegionLinux
sudo python/legion_linux/legion_linux/legion_gui.py

fancurve

Unexpected:

Changing and Setting your own Fan Curve with the Python CLI

You can do the same as the GUI from a CLI program. It will access the same presets.

# run from folder LenovoLegionLinux
sudo python/legion_linux/legion_linux/legion_cli.py
usage: legion_cli.py [-h] {fancurve-write-preset-to-hw,fancurve-write-hw-to-preset,fancurve-write-file-to-hw,fancurve-write-hw-to-file} ...

Legion CLI

options:
  -h, --help            show this help message and exit

subcommands:
  {fancurve-write-preset-to-hw,fancurve-write-hw-to-preset,fancurve-write-file-to-hw,fancurve-write-hw-to-file}
    fancurve-write-preset-to-hw
                        Write fan curve from preset to hardware
    fancurve-write-hw-to-preset
                        Write fan curve from hardware to preset
    fancurve-write-file-to-hw
                        Write fan curve from file to hardware
    fancurve-write-hw-to-file
                        Write fan curve from hardware to file

Creating and Setting your own Fan Curve with Script

Just run the script to set the fan curve. It is in the folder LenovoLegionLinux.

# Go to folder LenovoLegionLinux and run it. It should output "Writing fancurve successful!" if it finishes successful
sudo ./setmyfancurve.sh
# And check new fan curve
sudo cat /sys/kernel/debug/legion/fancurve

Open the file setmyfancurve.sh and edit it to adapt the values in the script to create your own fan curve. Follow the description in the file.

Unexpected output:

Note:

Change power mode from software

For this to work, you must install the kernel module permanently (see above). Alternatively, you can restart the the power daemon (systemctl restart power-profiles-daemon.service in Ubuntu) after reloading the kernel module (see above).

Modify/Control with GUI

With the GUI, the current power mode can be changed by selecting the mode in the box labeled with Power mode/platform profile.

Modify/Control with Widget

In Ubuntu/Gnome go to Settings->Power->Power Mode/Power Saving Option or the applet in the top right.

psensor

Automatic change of power mode can be changed in the settings of the distribution ( in Ubuntu).

Modify with CLI

# List all profiles (power-saver = quiet= blue)
powerprofilesctl list

#   performance:
#     Driver:     platform_profile
#     Degraded:   no

#   balanced:
#     Driver:     platform_profile

# * power-saver:
#     Driver:     platform_profile

# Set a profile, e.g. power-saver=quiet
powerprofilesctl set power-saver
# or balanced
powerprofilesctl set balanced
# or performance
powerprofilesctl set performance

Alternatively, you can also directly access it on a lower level:

# Access current profile
cat /sys/firmware/acpi/platform_profile

# Change current profile (AS ROOT): available modes quiet, balanced, performance, balanced-performance
# quiet = power-saver
echo quiet > /sys/firmware/acpi/platform_profile
# or balanced
echo balanced > /sys/firmware/acpi/platform_profile
# or performance
echo performance > /sys/firmware/acpi/platform_profile
# or custom-mode = balanced-performance (not available on all models); the LED should turn pink/purple
echo balanced-performance > /sys/firmware/acpi/platform_profile

Custom Power Mode

If you model support the custom power mode, then you can:

You can change to it with in the GUI: Open the GUI and select "Custom Mode" for power profile. Alternativley, you can change to it with in the command line with:

echo balanced-performance > /sys/firmware/acpi/platform_profile

Unfortunately, the power-profile-deamon or powerprofilesctl currently do not support this mode.

Enable or disable the mini fan curve

If the laptop stays cool for a longer time, it will enable the "mini fan curve", a special fan curve with only a few points. It will usually spin the fans. You can enable or disable that. If you want to use your configured fan curve in any case, disable it. The mini fan curve is not available on all models (you will see error for mini fan curve when running cat /sys/kernel/debug/legion/fancurve).

With the GUI, the mini fan curve is enabled/disabled by checking/unchecking the box Minifancurve if cold and pressing Apply to HW.

Lenovo Legion Laptop Support Daemon(legiond)

The LLL Daemon is supported in Systemd and OpenRC(Experimental). If you install LLL manually(not throngh the package manager), you may need to run the systemd_install.sh unside the extra folder.

This Daemon allow to chnage automatically bettwen fan profiles set in the gui depending of the power mode and if the laptop is or not plug in: These are the profiles avaiable:

Exemple profiles are here can also be set via the gui for easy set up: 1 - Set the Fan Curve you like to use 2 - Chose on the profile above in Fancurve Preset and hit Sate to Preset (will ask for you password) 3 - Set all the profiles 4 - Go to the Automation tab and enable the option Lenovo Legion Laptop Support Daemon Enable

This systemd service also have extras features that can be activated by editing legiond.ini located /etc/legion_linux/legiond.ini:

NOTE: legiond.service depends on acpid.service and if you enable legiond.service, acpid.service should be started automatically. If your CPU tweaks often get reset to default, enable legiond-cpuset.timer to override it.

See README.org

Lock and Unlock the Fan Controller and Fan Speed

You can lock the current fan speed. If it is locked, the fan speed will stays constant and does not react to temperature changes. You might want to lock the fan at a high speed during a game. I would not recommend keeping it locked all the time. If your fan controller gets locked accidentally, e.g. by Windows tools, you can unlock it. A locked fan controller might be the reason for a non-working fan control. If the fan controller is locked, the additional temperature sensors are not updated anymore and also stay constant.

With the GUI, the fan controller is locked by checking the box Lock fan controller and pressing Apply to HW.

Set Speed to Maximum Fan Speed

The fan can be set to maximum fan speed regardless of temperature. This is sometimes called extreme cooling mode or dust cleaning mode. Do not enable this for long periods of time, because it might degrade your fans faster.

With the GUI, the current fan speed is set to the maximum possible value by checking Set speed to maximum fan speed and pressing Apply to HW.

This is currently not available in many models.

Set Battery Conservation Mode to Prolong Battery Life when AC is plugged in

You can enable battery conservation mode. When conservation mode is enabled, the constant charging of the battery is disabled when the AC (charger) is plugged in. It will try to keep your battery state of charge at around 50%. This is said to prolong the battery life.

With the GUI, the battery conservation is enabled by checking the box Battery conservation (changes should apply immediately).

Toggle Fn lock to use special functions on F1-F12 keys without pressing Fn key

You can lock the Fn keys. You can do it by pressing Fn+Esc. This should also toggle the light in the Esc key (if available in your model). If enabled, the special functions, e.g. increase sound volume on F3, is triggered without pressing Fn.

With the GUI, the Fn-lock is enabled/disabled by checking/unchecking the box Fn Lock (changes should apply immediately).

Enable/Disable Touch Pad

You can enable or disable the touch pad. You can do it by pressing Fn+F10 (or similar).

With the GUI, the touch pad is enabled/disabled by checking/unchecking the box Touch Pad Enabled (changes should apply immediately).

Keyboard Backlight

Known Bugs

Some bugs cannot be fixed due to the firmware in the hardware:

:clap: Credits

Basis of this work

Thank you for your work on Windows tools that were the basis of the Linux support:

Contributors to Lenovo Legion Laptop Support

Thank you for your contribution for the Linux support:

Also please tell me if it works or does not work on your laptop.

Tools that are based on LenovoLegionLinux

Plasma Vantage

PlasmaVantage is a Plasma Widget for KDE. It is an alternative GUI for the LenovoLegionLinux kernel module. It is availabe in the KDE stroe or with source here.

:interrobang: Frequency Asked Questions

What are the new temperatures?

These are the temperatures measured and used by the embedded controller. Only they are relevant for the fan controller. They are provided by the new kernel module and otherwise not accessible because they are read from the embedded controller.

What are the new fan speed sensors?

They report the fan speed in revolutions per minute (rpm). They are provided by the new kernel module and otherwise not accessible because they are read from the embedded controller.

What temperatures are used for controlling the fan speed?

The CPU, GPU, and "IC" temperature is used. These are (usually) additional sensors that are different from the temperature sensors that are reported when you do not use the kernel model. In particular, the "IC" temperature limit might be set to a low value which results in almost-always running fans.

My CPU and GPU temperatures are low but the fan is still running?

See above. In particular, the "IC" temperature sensor.

Is the fan speed controlled by power consumption?

I have no reason to believe that. As far as I know and observed, only the temperatures are used.

My fans do not spin up, never stop, or never change speed (after using other tools)?

If they always have roughly constant speed, maybe you have locked the fan controller, often called locking fan speed. You can unlock/lock the fan speed controller in the GUI (see above). I would recommend not locking them. Doing a BIOS/UEFI update usually also unlocks it. But beware and consider making a BIOS (re)-update.

If the fans never spin up fast even under hight load, the fan controller might be locked (above). Additionally, also check that the reported temperatures for CPU (or GPU) really increase under load. Only, the temperatures "CPU Temperature", "GPU Temperature", and "IC Temperature" are used for fan control. These, are used internally by the fan controller in hardware.

If otherwise the fans never stop, you might have set a very low upper temperature limit for CPU, GPU or IC. Many models also come with a low temperature limit even on quiet mode, so fans never really turn off. You can just increase the temperature limits for the lowest level.

The fans are loud when idle.

See above.

The fans turn on when doing light work like browsing.

Even when browsing there might be small bursts of work for the CPU. So it gets hot for a short time and the fans turn on. You can:

The reported temperatures do not change or seem wrong.

See above.

Even under high load, the fans are not going fast enough.

See above.

After a BIOS update something, e.g. the fan controls, does not work anymore?

Maybe there was a problem during the BIOS update. Downgrade to an older version again. Then test it with the old version. Then do the BIOS upgrade again and check with the version.

How to do a BIOS upgrade or reset the embedded controller to fix a problem?

The easiest way is to downgrade to a older version and then upgrade to the current version again. Also test it with the old version. You can also just try reset the embedded controller by:

What does quiet, balanced, or performance mode do?

You can switch the mode by pressing Fn+Q and it will change the mode in the firmware and the color of the LED, even without any driver support (= without this kernel module).

Changing power mode without Lenovo Legion Linux is purely implemented in hardware:

Changing power mode with Lenovo Legion Linux:

On Windows it is similar: Changing the power mode is reported to the system or tools like Vantage which change the power plan.

Should I use balanced mode or performance for gaming?

The difference in usable performance (FPS) is minimal. Use performance mode to get the utmost highest performance, otherwise use the balanced mode.

One fan runs at full speed all the time. What should I do?

First check that the fan curve is set properly and this is not a misconfiguration. Then check if the temperatures used for fan control (see: "new temperatures") have low values on idle. If just one fan is on full speed but the other one is controlled according to fan curve, then you should reset the BIOS and EC controller.

What is "advanced thermal optimization" in the BIOS?

You can change the fan curve and minimal fan speed that are programmed into the hardware:

Also see: https://forums.lenovo.com/t5/Gaming-Laptops/Legion-7-Bios-What-is-advanced-thermal-optimization/m-p/5079357

I don't use GNOME. How do I get a nice widget for changing the power mode?

The power mode can be changed using Fn+Q.

If you use KDE, the power mode can be changed from the "Battery And Brightness" icon.

If you don't need a GUI, you could use the commandline.

For other desktop environments: This driver makes power mode changing available to tools like power-profiles-daemon.

First you should try changing from the terminal, see "Powermode -> Modify with CLI". If it works, then install power-profiles-daemon.

A graphical GNOME applet uses power-profiles-daemon to change the power mode using software. It is not provided by this tool, but is a standard tool already integrated into GNOME.

For KDE, there is the graphical tool powerdevil, which also uses power-profiles-daemon internally.

It almost works, but (some) temperature sensor/changing point in fan control or (some) fan speed is not working. What should I do?

First, try to reset the embedded controller OR do a BIOS update/downgrade to reset everything.

It does not work after a kernel update.

Option 1: Recompile/reinstall the module, see: Permanent Install Instructions. Option 2: Use DKMS to automate this process for every kernel update, see: Installing via DKMS

My screen is dimmed after a time of inactivity even if I disabled that in Ubuntu. How to fix that? (GNOME)

gsettings set org.gnome.settings-daemon.plugins.power idle-brightness 100

See: https://old.reddit.com/r/linuxquestions/comments/utle2w/ubuntu_2204_is_there_a_way_to_disable_screen/

How to power down the dGPU while not in use and use the iGPU for power saving instead?

This describes a way to configure and use it on Ubuntu using X11. It configures it such that everything runs on iGPU if not otherwise selected.

sudo cat /proc/driver/nvidia/gpus/0000:01:00.0/power

:question: Unanswered Questions

:information_desk_person: Overview for Developers

The software consists of two parts:

Legal Matters

Reference to any Lenovo products, services, processes, or other information and/or use of Lenovo Trademarks does not constitute or imply endorsement, sponsorship, or recommendation thereof by Lenovo.

The use of Lenovo®, Lenovo Legion™, Yoga®, IdeaPad® or other trademarks within this website and associated tools and libraries is only to provide a recognisable identifier to users to enable them to associate that these tools will work with Lenovo laptops.