{ 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; }; }