- Python 71.3%
- Shell 16.2%
- Nix 9.5%
- Makefile 3%
| conf | ||
| pkg | ||
| research/CFSV1-2/CF-SV1S14KS | ||
| src | ||
| systemd | ||
| tests | ||
| .build.yml | ||
| .gitignore | ||
| .rumdl.toml | ||
| .secrets.baseline | ||
| CHANGELOG.md | ||
| CONTRIBUTING.md | ||
| DESIGN.md | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| Makefile | ||
| mise.toml | ||
| prek.toml | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
| VERSION | ||
panafanpwr
- Project page: https://sr.ht/~szern/panafanpwr/
- Git repository: https://git.sr.ht/~szern/panafanpwr
- Issue tracker: https://todo.sr.ht/~szern/panafanpwr
- Mailing list (patches and discussions): https://lists.sr.ht/~szern/panafanpwr-devel
Fan and power profile control for Panasonic laptops on Linux.
Panasonic provides no Linux support for their laptops' power and fan controls. This fills that gap by writing to the Embedded Controller — unlocking performance modes and giving direct control over fan speed and curve.
Rather than replacing existing power management tools, panafanpwrd integrates with them. It watches power-profiles-daemon (or any compatible implementation) via DBus and automatically applies the right hardware settings whenever you switch between performance, balanced, and power-saver profiles — so GNOME, KDE, and anything else that drives power profiles just works, with the laptop actually responding correctly.
panafanpwrd exposes a Unix socket so the panafanpwr CLI can query state and make adjustments without sudo. It is compatible with anything that implements the org.freedesktop.UPower.PowerProfiles DBus interface — power-profiles-daemon, tuned-ppd, and tlp-pd.
| Product name | Status |
|---|---|
CF-SV1 (CFSV1-2) |
Supported |
| CF-QV9 | Experimental — based on community reports, not tested with this tool. Requires allow_experimental = true. Testing feedback → |
CF-SR4 (CFSR4-1) |
Supported Testing feedback → |
CF-SC6 (CFSC6-1) |
Supported Report → |
CF-SV8 (CFSV8-2) |
Supported Report → |
| CF-FV4 | Not yet supported — contributions very welcome, see CONTRIBUTING.md |
Product name: cat /sys/class/dmi/id/product_name
The daemon matches by product name (e.g. CFSV1-2), so all variants of a platform are auto-detected. If your specific model hasn't been tested yet, the daemon logs a warning asking you to report your results — this helps build a database of tested devices.
Requirements
- Linux with systemd
acpi_callkernel module- A
org.freedesktop.UPower.PowerProfilesDBus provider (power-profiles-daemon,tuned-ppd, ortlp-pd) - Python 3.11+ with
jeepney(the AUR package pulls this in automatically; if installing viamake install, also install pip and jeepney:pacman -S python-pip python-jeepneyor your distro's equivalent)
Tested on Arch Linux with tlp-pd. Should work on any systemd-based distro with a compatible power profiles provider.
Installation
1. Load the acpi_call kernel module (install it first if needed — on Arch Linux: acpi_call):
sudo modprobe acpi_call
# to persist across reboots:
echo acpi_call | sudo tee /etc/modules-load.d/acpi_call.conf
2. Install panafanpwr:
Arch Linux (AUR)
yay -S panafanpwr
The AUR package pulls in python-jeepney and power-profiles-daemon as dependencies automatically.
NixOS (flake)
The repo ships a flake with a package and a NixOS module. Add it as an input, pinned to a release tag so you only ever get tagged releases:
inputs.panafanpwr.url = "git+https://git.sr.ht/~szern/panafanpwr?ref=refs/tags/v0.4";
inputs.panafanpwr.inputs.nixpkgs.follows = "nixpkgs";
Your flake.lock freezes the exact revision either way; update with
nix flake update.
Then import the module and enable it. acpi_call is built against your
kernel and loaded at boot automatically, so the modprobe step above is
not needed:
imports = [ inputs.panafanpwr.nixosModules.default ];
services.panafanpwr.enable = true;
Per-profile overrides are Nix options instead of /etc/panafanpwrd.conf:
services.panafanpwr.settings."platform.CFSV1-2.profile.performance".power_mode = "perf";
The module always runs the daemon socket-activated — the packaged daemon
refuses to self-bind (--require-systemd-socket-activation) and the socket
lives in a RuntimeDirectory at /run/panafanpwr/panafanpwr.sock. To relocate
it:
services.panafanpwr.runtimeDirectory = "panafanpwrd";
The module exports the socket path as PANAFANPWR_SOCKET for interactive
panafanpwr callers (the CLI resolves --socket flag over env var over
default); the resume hook is wired explicitly.
The flake also exposes overlays.default and eval checks (nix flake check).
Manual (other distros)
Install jeepney first: pacman -S python-jeepney or your distro's equivalent.
git clone https://git.sr.ht/~szern/panafanpwr
cd panafanpwr
sudo make install
The Makefile pip-installs the Python package, plus the systemd units and example conf, to /usr/local by default. Override with PREFIX or DESTDIR. The CLI connects to /run/panafanpwr/panafanpwr.sock by default — override per call with --socket, or globally by exporting PANAFANPWR_SOCKET.
3. Enable and start the services:
sudo systemctl enable --now panafanpwrd.socket panafanpwrd-ppd.service
sudo systemctl enable panafanpwrd-resume.service
4. Verify:
panafanpwr status
If panafanpwr status reports not running, check the service:
systemctl status panafanpwrd-ppd.service
journalctl -u panafanpwrd-ppd.service --no-pager -S "24 hours ago"
Usage
panafanpwr <command> [options]
| Command | Description |
|---|---|
status |
Show current power mode and fan state |
power-mode [name] |
Set power mode; omit name to list available |
fan-profile [name] |
Set fan curve by name; omit name to list available |
fan-speed <0-100> |
Override fan speed manually (0 releases back to auto) |
reset |
Reapply settings for the current system power profile |
apply-system-power-profile <name> |
Apply platform config for a profile without changing the real system profile (for testing) |
All commands accept --json to print the raw daemon response, and --socket PATH to use a non-default socket.
CF-SV1 power modes
| Mode | Description |
|---|---|
perf |
Power limits unlocked, DPTF disabled |
eco |
DPTF power limits active (default) |
Power mode follows the system power profile automatically: performance maps to perf, balanced and power-saver map to eco. This mapping and the fan behaviour per profile are configurable — see Configuration below. Manual fan-profile or fan-speed overrides persist until the next profile change or resume.
CF-SV1 fan profiles
| Profile | Description |
|---|---|
quiet |
Firmware eco-path curve |
cool |
Firmware perf-path curve |
Configuration
/etc/panafanpwrd.conf is created on install (will not overwrite an existing file). All settings are optional — the daemon runs fine with no config file.
[daemon]
# profile_backend = power-profiles-daemon # or manual
# platform_id_override = CFSV1-2 # directly select platform, skip auto-detection
# allow_experimental = false # allow untested platforms (CFQV9, CFSR4, CFSC6-1)
[power-profile-backend.power-profiles-daemon]
# follow_system_power_profile = true # mirror power-profiles-daemon changes
Per-profile overrides let you customise the power mode and fan behaviour for each system power profile. All keys are optional; fan_profile and fan_speed are mutually exclusive.
[platform.CFSV1-2.profile.performance]
# power_mode = perf # override power mode (perf or eco)
# fan_profile = cool # set a fan curve (quiet or cool)
# fan_speed = 0 # or set a fixed speed (0 = release to auto, 100 = full)
[platform.CFSV1-2.profile.balanced]
# power_mode = eco
# fan_profile = quiet
[platform.CFSV1-2.profile.power-saver]
# power_mode = eco
# fan_profile = quiet
Experimental platforms
CF-QV9 is included based on ACPI analysis and community reports (source), but has not been tested with this daemon. Nothing is confirmed — please report your results.
To use an experimental platform, set allow_experimental = true in config. If your
hardware reports a matching product_name (CFQV9) it is auto-detected; if
not, also set platform_id_override to select it:
[daemon]
# allow_experimental = true
# platform_id_override = CFQV9 # only if not auto-detected
The daemon will refuse to start on an experimental platform without allow_experimental = true. If you try one of these platforms, please report your results (working or not) on the issue tracker.
Contributing
Bugs, questions, and hardware reports are welcome on the issue tracker. If your model isn't supported yet, opening an issue is a great starting point — please include your product name and SKU:
cat /sys/class/dmi/id/product_name
cat /sys/class/dmi/id/product_sku
cat /sys/class/dmi/id/product_version
Patches go to the mailing list via plain-text email. See CONTRIBUTING.md for how to send patches and how to add support for new hardware.
Uninstall
sudo make uninstall
/etc/panafanpwrd.conf is left in place.
Please don't upload my code to GitHub
Please don't upload my code to GitHub. The canonical home is on Sourcehut. Please don't mirror it to GitHub.
License
GPL-3.0-or-later. See LICENSE.