Open-source project
pop-os/system76-power avatar
pop-os/system76-power

system76-power drives graphics switching and power profiles on System76 laptops

Power profile management for Linux

643 stars80 forksRustGPL-3.0

At a glance

What is it?
system76-power is a Rust utility and D-Bus service that manages the switchable graphics modes and the power profiles on System76 laptops, including the PRIME render offloading setup and the GPIO based hotplug detection that prompts a switch when a display is plugged in. It installs a polkit policy and a systemd unit, and it is licensed under GPL-3.0.
Who is it for?
Adopt system76-power if you are running a System76 laptop or all-in-one on Linux and want switchable graphics, PRIME offloading and the three power profiles handled by one D-Bus service with a polkit policy, instead of hand editing sysfs and driver configuration.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A daemon that owns the graphics mode

system76-power is a utility for managing graphics and power profiles, and it is written in Rust. The repository listing describes it as power profile management for Linux, and the home of the project is the Pop!_OS organisation.

The interesting design decision is that this is not a one shot command. It installs a D-Bus interface, a systemd service and a polkit policy, so the machine's graphics mode is a property of the running system rather than a value you set once. The install target of the Makefile shows the four pieces that get placed on the filesystem:

bash
	install -D -m 0644 "data/$(ID).conf" "$(DESTDIR)$(datadir)/dbus-1/system.d/$(ID).conf"
	install -D -m 0644 "data/$(ID).policy" "$(DESTDIR)$(datadir)/polkit-1/actions/$(ID).policy"
	install -D -m 0644 "data/$(ID).service" "$(DESTDIR)$(libdir)/systemd/system/$(ID).service"
	install -D -m 0644 "data/$(ID).xml" "$(DESTDIR)$(datadir)/dbus-1/interfaces/$(ID).xml"
	install -D -m 0755 "target/release/$(BIN)" "$(DESTDIR)$(bindir)/$(BIN)"

The D-Bus configuration allows the service to be reached over the system bus, the polkit policy governs which users may change privileged settings, the systemd unit keeps the service running, and the XML file is the interface definition. The identifier used for all of them is com.system76.PowerDaemon.

That structure is why the project is more than a settings script. Anything that wants to change the graphics mode talks to the same service, including the GNOME extension that the readme points at.

Four graphics modes, and a reboot for every change

The readme describes four modes. Integrated uses the graphics controller on the Intel or AMD CPU exclusively, which means lower graphical performance with a longer battery life, and external displays connected to the dGPU ports cannot be used.

NVIDIA uses the discrete GPU exclusively, giving higher graphical performance at the cost of a shorter battery life, and it allows using external displays.

Hybrid enables PRIME render offloading, where the integrated GPU is the primary renderer but specific applications can render on the discrete one.

Compute uses the integrated graphics controller exclusively for rendering and makes the discrete GPU available as a compute node, which is the mode for machine learning workloads that do not need a display.

Two constraints apply to all of them. Switchable graphics is a feature for laptops and all-in-one PCs and is not supported on desktops. And a reboot is required for changes to take effect after switching modes, which is the single most important operational fact about the tool, because it means a graphics switch is never applied on the fly.

PRIME offloading comes with driver version floors

The hybrid mode is where the detail is, and it comes with three separate prerequisites that the readme spells out.

PRIME render offloading requires the 435.17 NVIDIA drivers or later. Applications must use GLVND to take advantage of the feature, so an application may not render on the discrete GPU even when it is asked to. Vulkan applications must be launched with __NV_PRIME_RENDER_OFFLOAD=1 to render on the dGPU, and GLX applications must be launched with __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia.

Display offload sinks, described as reverse PRIME, require the 450.57 NVIDIA drivers or later, and that feature is what allows using external displays while in hybrid mode. Without it, hybrid mode on a laptop with a discrete GPU means giving up the external displays, which for many users is a hard requirement rather than a preference.

The practical consequence is that the mode you can use depends on the driver version installed, and the failure mode is quiet. An application that ignores the environment variables simply renders on the integrated GPU, and nothing errors out.

Runtime power management is a property of the GPU model

For the machine to enter a low power state when the discrete GPU is not being used, the card has to support run-time power management, and the readme is explicit that only Turing cards and newer fully implement this functionality.

There is a concrete way to check, and the readme walks through it. You read the PCI device identifier and then look the device up in the supported-gpus.json file that the driver ships:

bash
$ cat /sys/bus/pci/devices/0000:01:00.0/device
0x1f15
$ jq '.chips[] | select(.devid=="0x1F15")' < /usr/share/doc/nvidia-driver-460/supported-gpus.json
{
  "devid": "0x1F15",
  "name": "GeForce RTX 2060",
  "features": [
    "dpycbcr420",
    "dpgsynccompatible",
    "hdmi4k60rgb444",
    "hdmigsynccompatible",
    "geforce",
    "runtimepm",
    "vdpaufeaturesetJ"
  ]

The runtimepm entry in the features list is the one to look for. Without it, a laptop that switches to integrated graphics can still draw power from the discrete card that never sleeps, which is exactly the situation this tool exists to avoid.

Note that the path in the example points at the 460 driver package, so the file moves as the driver version changes.

Three profiles, each layered on the one above

The power profiles are cumulative, and the readme is explicit about the inheritance.

Balanced is the base. It sets the sync data to disk to 15 seconds, enables the laptop mode feature in the kernel, enables SCSI and SATA link time power management, and controls the Intel PState values if they exist.

Performance uses the settings from Balanced and adds the ACPI platform profile where the hardware is supported by the kernel.

Battery uses the settings from Performance, sets the screen brightness to a lower value and turns the keyboard backlight off.

Two things stand out. First, the layering means Battery inherits Performance inherits Balanced, so choosing Battery does not undo the balanced settings, it stacks on them. Second, the user facing differences in Battery are partly cosmetic, since screen brightness and keyboard backlight are visible but the underlying power settings come from the profile below.

The Balanced profile is also where the sysfs and kernel interfaces show through, since sync intervals, kernel laptop mode, SATA link power management and Intel PState values are all kernel level knobs. On hardware without Intel PState, the corresponding steps simply do not apply, and the readme words it as if they exist.

Hotplug detection is GPIO work on specific hardware

The D-Bus signal HotPlugDetect is sent when a display is plugged into a port connected to the discrete GPU. If the system is in integrated or compute mode, the GNOME extension prompts to switch to hybrid mode so the display can be used.

Making that work on a new model is the part of the project that is most hardware specific, and the readme explains how the mapping is derived. For Intel based systems, the GPIO sideband port and pins for the display ports are determined with the schematics and the output of coreboot-collector. The schematics show which GPIOs are display ports, marked as *_HPD, and the corresponding GPP_* entry in coreboot-collector.txt carries the port and pin tuple.

Some models mux the DisplayPort output between mDP and USB-C, and those units have a separate data switch pin used to determine which output is in use.

For AMD based systems, a MMIO region for FCH GPIO controls is used to detect external display plug events. Display ports still use the *_HPD naming, but they do not necessarily map to a literal GPIO, with HDMI_HPD mapping to DP3_HPD on kudu6 as the example given. For those, the suggested method is to generate a diff from coreboot-collector in NVIDIA mode before and after plugging in a display, which yields the GPIO number.

That is a genuinely hardware dependent procedure, and it means support for a new machine is not a matter of running the daemon but of doing that research first.

The Rust implementation and its dependencies

The crate is named system76-power at version 1.2.8, edition 2021, requiring rust-version 1.75.0, and it is authored by Jeremy Soller. It is a Cargo workspace with one member, a local crate called zbus that provides the system76-power-zbus dependency.

The dependency list explains the design. zbus at version 3.15.2 with the tokio feature is the D-Bus implementation, zbus_polkit brings in the polkit integration, and zvariant handles the value types. tokio is the async runtime, restricted to the macros, rt, time and signal features, and futures-lite is used alongside it.

The rest of the dependencies map onto the features described in the readme. intel-pstate handles the processor state values, hidapi covers the HID access used for keyboard backlight and fan control, inotify watches for changes, fern and log provide logging, clap handles the command line parsing, and serde with serde_json handle configuration and the JSON files. A git dependency, sysfs-class from the pop-os organisation, points at the sysfs attribute helpers.

The repository also carries an examples/ directory with small programs named autoswitch.rs, fan.rs, gpio.rs, graphics.rs and hid.rs, which are useful reading for the individual subsystems, plus a TESTING.md, a rust-toolchain.toml and a rustfmt.toml.

GPL-3.0 and a commit history with no tagged releases

The licence is GPL-3.0, which is a meaningful choice for a system service. Linking and shipping this daemon in a product carries copyleft obligations on the combined work, unlike the permissive licences used by most of the other utilities in this repository set, and anyone embedding it should have their legal team look at it.

There are no GitHub releases, so the Cargo.toml version is the version marker, and the version in the tree is 1.2.8. The last push was on 2026-10-19 and the repository is not archived, so the project is being worked on regularly even without tagged release notes.

The build itself is plain Cargo with a Makefile around it. The default target builds the release binary, a clean target runs cargo clean, an update target runs cargo update, and a vendor target creates a vendored dependency directory with cargo vendor for reproducible offline builds. The install target copies the four data files and the binary into the prefix, and the uninstall target removes them, which is a signal that this is packaged for distribution systems rather than run from a source checkout.

For an adopter, the practical question is which distribution packages it. The repository carries a debian/ directory, which is the packaging route for Debian derived systems including Pop!_OS and Ubuntu.

Editorial conclusion

Adopt system76-power if you are running a System76 laptop or all-in-one on Linux and want switchable graphics, PRIME offloading and the three power profiles handled by one D-Bus service with a polkit policy, instead of hand editing sysfs and driver configuration. Skip it on desktops, where switchable graphics is not supported, or if you are on hardware whose GPIO pin mapping is not documented, because hotplug detection then needs the schematics and the coreboot-collector output. Before you deploy it, read TESTING.md, check the NVIDIA driver version against the 435.17 and 450.57 floors for offloading and display sinks, and confirm your GPU appears with the runtimepm feature in the driver supported-gpus.json file.

Frequently asked questions

What does system76-power manage?

It is a utility for managing graphics and power profiles on System76 laptops and all-in-one PCs. The graphics modes are integrated, NVIDIA, hybrid and compute, and the power profiles are balanced, performance and battery.

Does switching graphics modes require a reboot?

Yes. The readme states that a reboot is required for changes to take effect after switching modes. Switchable graphics is also not supported on desktops, only on laptops and all-in-one PCs.

What do the NVIDIA driver versions have to do with hybrid mode?

PRIME render offloading requires the 435.17 NVIDIA drivers or later, and display offload sinks, called reverse PRIME, require 450.57 or later. Vulkan applications also need __NV_PRIME_RENDER_OFFLOAD=1, and GLX applications need __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia.

How do I check whether my GPU supports run-time power management?

Read the PCI device identifier from /sys/bus/pci/devices and look the device up in the supported-gpus.json file shipped with the driver. The runtimepm feature in that entry is the indicator, and the readme notes that only Turing cards and newer fully implement it.

How does system76-power handle plugging in an external display?

It sends the HotPlugDetect D-Bus signal when a display is connected to a port attached to the dGPU, and if the system is in integrated or compute mode the GNOME extension prompts to switch to hybrid mode. Adding hotplug detection to a new model requires mapping the display port GPIOs from the schematics and the coreboot-collector output.

What does installing system76-power put on the system?

The Makefile installs a D-Bus system configuration, a polkit action policy, a systemd service unit, the D-Bus interface XML and the binary itself, all under the identifier com.system76.PowerDaemon. The crate is version 1.2.8, requires Rust 1.75.0 and is licensed under GPL-3.0.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. pop-os/system76-power on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pop-os-system76-power.svg)](https://hysenlabs.com/projects/pop-os-system76-power)

Was this useful?