blob: c553a381f772ee664470ec40100c8d8a2276e16a [file] [edit]
.. SPDX-License-Identifier: GPL-2.0-only
===============================================================================================
Kernel driver yogafan
===============================================================================================
Supported chips:
* Lenovo Yoga, Legion, IdeaPad, Slim, Flex, and LOQ Embedded Controllers
* Prefix: 'yogafan'
* Addresses: ACPI handle (See Database Below)
Author: Sergio Melas <sergiomelas@gmail.com>
Description
-----------
This driver provides fan speed monitoring for modern Lenovo consumer laptops.
Most Lenovo laptops do not provide fan tachometer data through standard
ISA/LPC hardware monitoring chips. Instead, the data is stored in the
Embedded Controller (EC) and exposed via ACPI.
The driver implements a **Rate-Limited Lag (RLLag)** filter to handle
the low-resolution and jittery sampling found in Lenovo EC firmware.
Hardware Identification and Multiplier Logic
--------------------------------------------
The driver supports two distinct EC architectures. Differentiation is handled
deterministically via a DMI Product Family quirk table during the probe phase,
eliminating the need for runtime heuristics.
1. 8-bit EC Architecture (Multiplier: 100)
- **Families:** Yoga, IdeaPad, Slim, Flex.
- **Technical Detail:** These models allocate a single 8-bit register for
tachometer data. Since 8-bit fields are limited to a value of 255, the
BIOS stores fan speed in units of 100 RPM (e.g., 42 = 4200 RPM).
2. 16-bit EC Architecture (Multiplier: 1)
- **Families:** Legion, LOQ.
- **Technical Detail:** High-performance gaming models require greater
precision for fans exceeding 6000 RPM. These use a 16-bit word (2 bytes)
storing the raw RPM value directly.
Filter Details
--------------
The RLLag filter is a passive discrete-time first-order lag model that ensures:
- **Smoothing:** Low-resolution step increments are smoothed into 1-RPM increments.
- **Slew-Rate Limiting:** Prevents unrealistic readings by capping the change
to 1500 RPM/s, matching physical fan inertia.
- **Polling Independence:** The filter math scales based on the time delta
between userspace reads, ensuring a consistent physical curve regardless
of polling frequency.
Suspend and Resume
------------------
The driver utilizes the boottime clock (ktime_get_boottime()) to calculate the
sampling delta. This ensures that time spent in system suspend is accounted
for. If the delta exceeds 5 seconds (e.g., after waking the laptop), the
filter automatically resets to the current hardware value to prevent
reporting "ghost" RPM data from before the sleep state.
Usage
-----
The driver exposes standard hwmon sysfs attributes:
=============== ============================
Attribute Description
fanX_input Filtered fan speed in RPM.
=============== ============================
Note: If the hardware reports 0 RPM, the filter is bypassed and 0 is reported
immediately to ensure the user knows the fan has stopped.
====================================================================================================
LENOVO FAN CONTROLLER: MASTER REFERENCE DATABASE (2026)
====================================================================================================
::
MODEL (DMI PN) | FAMILY / SERIES | EC OFFSET | FULL ACPI OBJECT PATH | WIDTH | MULTiplier
----------------------------------------------------------------------------------------------------
82N7 | Yoga 14cACN | 0x06 | \_SB.PCI0.LPC0.EC0.FANS | 8-bit | 100
80V2 / 81C3 | Yoga 710/720 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100
83E2 / 83DN | Yoga Pro 7/9 | 0xFE | \_SB.PCI0.LPC0.EC0.FANS | 8-bit | 100
82A2 / 82A3 | Yoga Slim 7 | 0x06 | \_SB.PCI0.LPC0.EC0.FANS | 8-bit | 100
81YM / 82FG | IdeaPad 5 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100
82JW / 82JU | Legion 5 (AMD) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FANS (Fan1) | 16-bit | 1
82JW / 82JU | Legion 5 (AMD) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FA2S (Fan2) | 16-bit | 1
82WQ | Legion 7i (Int) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FANS (Fan1) | 16-bit | 1
82WQ | Legion 7i (Int) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FA2S (Fan2) | 16-bit | 1
82XV / 83DV | LOQ 15/16 | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FANS /FA2S | 16-bit | 1
83AK | ThinkBook G6 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100
81X1 | Flex 5 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100
*Legacy* | Pre-2020 Models | 0x06 | \_SB.PCI0.LPC.EC.FAN0 | 8-bit | 100
----------------------------------------------------------------------------------------------------
METHODOLOGY & IDENTIFICATION:
1. DSDT ANALYSIS (THE PATH):
BIOS ACPI tables were analyzed using 'iasl' and cross-referenced with
public dumps. Internal labels (FANS, FAN0, FA2S) are mapped to
EmbeddedControl OperationRegion offsets.
2. EC MEMORY MAPPING (THE OFFSET):
Validated by matching NBFC (NoteBook FanControl) XML logic with DSDT Field
definitions found in BIOS firmware.
3. DATA-WIDTH ANALYSIS (THE MULTIPLIER):
- 8-bit (Multiplier 100): Standard for Yoga/IdeaPad. Raw values (0-255).
- 16-bit (Multiplier 1): Standard for Legion/LOQ. Two registers (0xFE/0xFF).
References
----------
1. **ACPI Specification (Field Objects):** Documentation on how 8-bit vs 16-bit
fields are accessed in OperationRegions.
https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#field-objects
2. **NBFC Projects:** Community-driven reverse engineering
of Lenovo Legion/LOQ EC memory maps (16-bit raw registers).
https://github.com/hirschmann/nbfc/tree/master/Configs
3. **Linux Kernel Timekeeping API:** Documentation for ktime_get_boottime() and
handling deltas across suspend states.
https://www.kernel.org/doc/html/latest/core-api/timekeeping.html
4. **Lenovo IdeaPad Laptop Driver:** Reference for DMI-based hardware
feature gating in Lenovo laptops.
https://github.com/torvalds/linux/blob/master/drivers/platform/x86/ideapad-laptop.c