240 lines
7.3 KiB
Nix
240 lines
7.3 KiB
Nix
{ pkgs, lib, ... }:
|
|
let
|
|
battery-limit-script = pkgs.writeShellScriptBin "set-battery-limit" ''
|
|
#!/bin/bash
|
|
echo 40 > /sys/class/power_supply/BAT0/charge_control_start_threshold
|
|
echo 80 > /sys/class/power_supply/BAT0/charge_control_end_threshold
|
|
'';
|
|
gpu-limit-frequency = pkgs.writeShellScriptBin "set-gpu-limit" ''
|
|
#!/bin/bash
|
|
start() {
|
|
${pkgs.intel-gpu-tools}/bin/intel_gpu_frequency -e
|
|
}
|
|
|
|
stop() {
|
|
${pkgs.intel-gpu-tools}/bin/intel_gpu_frequency -d
|
|
}
|
|
'';
|
|
tuned-auto-profile-config = ''
|
|
# TuneD rules for recommend_profile.
|
|
#
|
|
# Syntax:
|
|
# [PROFILE1]
|
|
# KEYWORD11=RE11
|
|
# KEYWORD21=RE12
|
|
#
|
|
# [PROFILE2]
|
|
# KEYWORD21=RE21
|
|
# KEYWORD22=RE22
|
|
|
|
# KEYWORD can be:
|
|
# virt - for RE to match output of virt-what
|
|
# system - for RE to match content of /etc/system-release-cpe
|
|
# process - for RE to match running processes. It can have arbitrary
|
|
# suffix, all process* lines have to match for the PROFILE
|
|
# to match (i.e. the AND operator)
|
|
# /FILE - for RE to match content of the FILE, e.g.:
|
|
# '/etc/passwd=.+'. If file doesn't exist, its RE will not
|
|
# match.
|
|
# chassis_type - for RE to match the chassis type as reported by dmidecode
|
|
# syspurpose_role - for RE to match the system role as reported by syspurpose
|
|
|
|
# All REs for all KEYWORDs have to match for PROFILE to match (i.e. the AND operator).
|
|
# If 'virt' or 'system' is not specified, it matches for every string.
|
|
# If 'virt' or 'system' is empty, i.e. 'virt=', it matches only empty string (alias for '^$').
|
|
# If several profiles matched, the first match is taken.
|
|
#
|
|
# Limitation:
|
|
# Each profile can be specified only once, because there cannot be
|
|
# multiple sections in the configuration file with the same name
|
|
# (ConfigParser limitation).
|
|
# If there is a need to specify the profile multiple times, unique
|
|
# suffix like ',ANYSTRING' can be used. Everything after the last ','
|
|
# is stripped by the parser, e.g.:
|
|
#
|
|
# [balanced,1]
|
|
# /FILE1=RE1
|
|
#
|
|
# [balanced,2]
|
|
# /FILE2=RE2
|
|
#
|
|
# This will set 'balanced' profile in case there is FILE1 matching RE1 or
|
|
# FILE2 matching RE2 or both.
|
|
|
|
# Profile for devices on battery
|
|
[doloro-power-saver]
|
|
virt=
|
|
system=
|
|
/sys/class/power_supply/BAT0/status=Discharging
|
|
|
|
# Profile for devices on AC power
|
|
[doloro-balanced]
|
|
virt=
|
|
system=
|
|
/sys/class/power_supply/BAT0/status=Charging
|
|
|
|
[atomic-host]
|
|
virt=
|
|
system=.*atomic.*
|
|
|
|
[atomic-guest]
|
|
virt=.+
|
|
system=.*atomic.*
|
|
|
|
[throughput-performance]
|
|
virt=
|
|
system=.*(computenode|server).*
|
|
|
|
[virtual-guest]
|
|
virt=.+
|
|
|
|
[balanced]
|
|
'';
|
|
in
|
|
{
|
|
# services.power-profiles-daemon.enable = true;
|
|
# services.tlp = {
|
|
# enable = true;
|
|
# settings = {
|
|
# CPU_ENERGY_PERF_POLICY_ON_BAT = "powersave";
|
|
#
|
|
# # Wireless power saving
|
|
# WIFI_PWR_ON_BAT = "1";
|
|
#
|
|
# # USB autosuspend
|
|
# USB_AUTOSUSPEND = "1";
|
|
#
|
|
# # SATA drive power management
|
|
# SATA_LINKPWR_ON_BAT = "min_power";
|
|
#
|
|
# # PCI Express Active-State Power Management (ASPM)
|
|
# PCIE_ASPM_ON_BAT = "powersave";
|
|
#
|
|
# # Runtime Power Management for PCI(e) buses/devices
|
|
# RUNTIME_PM_ON_BAT = "auto";
|
|
#
|
|
# # Disable Bluetooth on battery
|
|
# # DEVICES_TO_DISABLE_ON_BAT = "bluetooth";
|
|
#
|
|
# # Restore brightness on battery
|
|
# RESTORE_BRIGHTNESS_ON_BAT = "1";
|
|
# CPU_ENERGY_PERF_POLICY_ON_AC = "balance_performance";
|
|
# # CPU_ENERGY_PERF_POLICY_ON_BAT = "power";
|
|
# CPU_ENERGY_PERF_POLICY_ON_SAV = "power";
|
|
# CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
|
|
# # PCIE_ASPM_ON_BAT = "powersave";
|
|
# CPU_SCALING_GOVERNOR_ON_AC = "balanced";
|
|
# PCIE_ASPM_ON_AC = "balanced";
|
|
# CPU_BOOST_ON_AC = 1;
|
|
# CPU_BOOST_ON_BAT = 0;
|
|
# CPU_BOOST_ON_SAV = 0;
|
|
# DEVICES_TO_DISABLE_ON_BAT_NOT_IN_USE = "bluetooth wifi wwan";
|
|
# INTEL_GPU_MIN_FREQ_ON_AC = 0;
|
|
# INTEL_GPU_MIN_FREQ_ON_BAT = 0;
|
|
# INTEL_GPU_MAX_FREQ_ON_AC = 2350;
|
|
# INTEL_GPU_MAX_FREQ_ON_BAT = 1100;
|
|
# INTEL_GPU_BOOST_FREQ_ON_BAT = 1100;
|
|
#
|
|
# TLP_DEFAULT_BATTERY_MODE = "SAV";
|
|
# CPU_HWP_DYN_BOOST_ON_AC = 1;
|
|
# CPU_HWP_DYN_BOOST_ON_BAT = 0;
|
|
# CPU_HWP_DYN_BOOST_ON_SAV = 0;
|
|
# PLATFORM_PROFILE_ON_AC = "balanced";
|
|
# PLATFORM_PROFILE_ON_BAT = "low-power";
|
|
# PLATFORM_PROFILE_ON_SAV = "quiet";
|
|
# START_CHARGE_THRESH_BAT0 = 40; # 40 and below it starts to charge
|
|
# STOP_CHARGE_THRESH_BAT0 = 80; # 80 and above it stops charging
|
|
# };
|
|
# };
|
|
services.tuned = {
|
|
enable = true;
|
|
profiles = {
|
|
doloro-power-saver = {
|
|
main = {
|
|
include = "powersave";
|
|
};
|
|
script = {
|
|
script = "${battery-limit-script}/bin/set-battery-limit,${gpu-limit-frequency}/bin/set-gpu-limit";
|
|
};
|
|
};
|
|
doloro-balanced = {
|
|
main = {
|
|
include = "balanced";
|
|
};
|
|
script = {
|
|
script = "${battery-limit-script}/bin/set-battery-limit";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
environment.etc = {
|
|
"tuned/recommend.conf" = {
|
|
text = tuned-auto-profile-config;
|
|
};
|
|
};
|
|
systemd.services = {
|
|
# Tells tuned "hey, re-eval system state and change profiles accordingly"
|
|
send-sighup-to-tuned = {
|
|
serviceConfig = {
|
|
ExecStart = "${pkgs.killall}/bin/killall -1 .tuned-wrapped";
|
|
Restart = "always";
|
|
RestartSec = "30s";
|
|
};
|
|
wantedBy = [ "multi-user.target" ];
|
|
};
|
|
tuned-auto-profile = {
|
|
description = "Enable Auto Profile in TuneD";
|
|
after = [ "network.target" ]; # Ensure network is up (if needed for TuneD)
|
|
wantedBy = [ "multi-user.target" ]; # Start in the default target mode
|
|
|
|
# Command to run
|
|
serviceConfig = {
|
|
ExecStart = "${pkgs.tuned}/bin/tuned-adm auto_profile";
|
|
Restart = "on-failure";
|
|
RestartSec = 5; # Wait 5 seconds before retrying if it fails
|
|
Environment = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; # Ensure PATH is correct
|
|
};
|
|
};
|
|
};
|
|
services.thermald.enable = true;
|
|
services.upower = {
|
|
enable = true;
|
|
};
|
|
boot.kernelParams = [
|
|
# "mem_sleep_default=deep"
|
|
"i915.fastboot=1"
|
|
"pcie_aspm=force"
|
|
"ahci.mobile_lpm_policy=1"
|
|
];
|
|
services.logind.settings.Login = {
|
|
HandleLidSwitch = "suspend";
|
|
HandleLidSwitchExternalPower = "suspend";
|
|
HandleLidSwitchDocked = "ignore";
|
|
};
|
|
systemd.sleep.extraConfig = ''
|
|
HibernateDelaySec=30min
|
|
SuspendEstimationSec=120
|
|
'';
|
|
|
|
systemd.services.rfkill-sleep-wake = {
|
|
enable = true;
|
|
description = "Using rfkill; disable all rf devices before sleeping.";
|
|
before = [ "sleep.target" ];
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStop = ''${pkgs.utillinux}/bin/rfkill unblock all'';
|
|
ExecStart = ''${pkgs.utillinux}/bin/rfkill block all'';
|
|
RemainAfterExit = true;
|
|
};
|
|
wantedBy = [ "sleep.target" ];
|
|
partOf = [ "sleep.target" ];
|
|
|
|
};
|
|
# one of "ignore", "poweroff", "reboot", "halt", "kexec", "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate", "lock"
|
|
powerManagement = {
|
|
enable = true;
|
|
# powertop.enable = true;
|
|
};
|
|
}
|