Skip to content

emomaxd/hpfand

Repository files navigation

hpfand

Fan curve daemon for HP Victus/Omen laptops on Linux. The firmware resets fan settings periodically and ramps aggressively. This daemon re-applies a configurable PWM curve every poll cycle to keep fans under control.

Compatibility

ls /sys/devices/platform/hp-wmi/hwmon/hwmon*/pwm1 2>/dev/null \
  && echo "supported" || echo "pwm1 not found — see Getting the module"

Supported boards (cat /sys/class/dmi/id/board_name): 8BBE 8BD4 8BD5 8C99 8C9C 8D41 (Victus), 8BAB 8BCA 8BCD 8C76 8C78 8A4D (Omen).

Linux ≥ 7.1: skip to Install. Older kernels: see Getting the module.


Install

git clone https://github.com/emomaxd/hpfand
cd hpfand
sudo ./install.sh

Or via AUR (Arch-based):

paru -S hpfand                  # Linux >= 7.1
paru -S hpfand hp-wmi-dkms      # older kernels

Usage

hpf status              # cpu/gpu temp, fan rpm, pwm, active preset
hpf status -w           # watch mode — refresh every 2s
hpf presets             # list available presets
hpf toggle              # toggle silent mode on/off — no root needed, persists across reboots
hpf log                 # show last 50 journal entries
sudo hpf set balanced     # apply a preset (silent / balanced / performance)
sudo hpf follow           # auto-track system power profile
sudo hpf pwm 120          # lock fans at fixed pwm — stops daemon, no thermal protection
sudo hpf edit             # edit /etc/hpfand.conf in $EDITOR

Example output of hpf status:

preset:  auto (follow profile)
mode:    manual (daemon active)
profile: balanced
---
cpu:     61°C
gpu:     43°C
fan1:    2900 rpm
fan2:    2900 rpm
pwm:     110/255

Presets

preset fans off until max speed at hysteresis poll
silent 50°C 90°C 8°C 4s
balanced 40°C 82°C 6°C 2s
performance 35°C 78°C 4°C 1s

sudo hpf follow maps low-power→silent, balanced→balanced, performance→performance automatically.


Custom curve

/etc/hpfand.conf:

CT=(40 50 60 72 82)    # CPU temp thresholds in °C
CP=(0  30 80 170 240)  # PWM values (0–255) at each threshold

HYST=6                 # ramp-down hysteresis in °C
POLL_SEC=2

# Optional: separate GPU curve (defaults to CPU curve if omitted)
GPU_CT=(45 55 65 75 85)
GPU_CP=(0  40 100 180 255)

FOLLOW_PLATFORM_PROFILE=0  # set to 1 to auto-track power profile
RPM_STALL_WARN=1           # warn in journal if fan stalls at high PWM

The daemon uses max(cpu_pwm, gpu_pwm) each cycle. Points are linearly interpolated. Ramp-up is immediate; ramp-down waits until temp drops HYST degrees below the last ramp-up point.

If inotify-tools is installed, the conf reloads automatically on save. Test without writing to hardware:

sudo hpfand --dry-run

Getting the module

The pwm1 hwmon interface is in the in-tree hp_wmi driver. The required fixes landed in Linux 7.1 (Phoronix, kernel.org).

Older kernels: use build-module.sh to build and load the patched driver automatically.

Requirements

Distro Command
Arch / Manjaro sudo pacman -S linux-headers
Ubuntu / Debian sudo apt install linux-headers-$(uname -r)
Fedora sudo dnf install kernel-devel

Also make sure git and make are installed (base-devel / build-essential cover both).

Build and load

sudo ./build-module.sh

This sparse-clones only the driver file from the patched branch, builds the module, loads it, and installs it so it survives reboots (until the next kernel update). Then run sudo ./install.sh as usual.

The module only persists for the current kernel version. After a kernel update, run build-module.sh again — or use hp-wmi-dkms (AUR) to handle this automatically.

Manual steps (if the script doesn't work)
git clone https://github.com/emomaxd/linux -b hp-wmi-victus-fan-v4 --depth=1
cd linux
mkdir /tmp/hp-wmi-build
cp drivers/platform/x86/hp/hp-wmi.c /tmp/hp-wmi-build/
echo 'obj-m += hp-wmi.o' > /tmp/hp-wmi-build/Makefile
make -C /lib/modules/$(uname -r)/build M=/tmp/hp-wmi-build modules
sudo rmmod hp_wmi
sudo insmod /tmp/hp-wmi-build/hp-wmi.ko
# persist until next kernel update:
sudo cp /tmp/hp-wmi-build/hp-wmi.ko /lib/modules/$(uname -r)/updates/hp-wmi.ko
sudo depmod -a

Patches in hp-wmi-victus-fan-v4: return value fixes, keep-alive timer, gpu_delta underflow, concurrent access locking.


Troubleshooting

Daemon not starting — hp-wmi hwmon not found — module not loaded. See Getting the module.

Fan speed doesn't change — run hpf status (mode should be manual (daemon active)) and hpf log 20 for errors.

build-module.sh fails at make — kernel headers missing. Install for your kernel (pacman -S linux-headers / apt install linux-headers-$(uname -r)) then retry.

Fans wrong after kernel update — module is version-specific. Run sudo ./build-module.sh again, or use hp-wmi-dkms (AUR).

GPU temp not shown — dGPU is in D3cold (off). Appears automatically when GPU becomes active.


Uninstall

sudo ./uninstall.sh