This repository has no description
2.9 kB
111 lines
1{ pkgs, ... }:
2let
3 # Find hwmon device by name and return path to specific file
4 # Usage: findHwmon "k10temp" "temp1_input" -> /sys/class/hwmon/hwmonX/temp1_input
5 gpd-fan-control = pkgs.writeShellScript "gpd-fan-control" ''
6 set -euo pipefail
7
8 # Configuration
9 INTERVAL=2
10 MINTEMP=55000 # millidegrees - fan off below this
11 MAXTEMP=90000 # millidegrees - fan full above this
12 MINPWM=0
13 MAXPWM=255
14
15 # Find hwmon paths by name
16 find_hwmon() {
17 local name=$1
18 for hwmon in /sys/class/hwmon/hwmon*; do
19 if [[ -f "$hwmon/name" ]] && [[ "$(cat "$hwmon/name")" == "$name" ]]; then
20 echo "$hwmon"
21 return 0
22 fi
23 done
24 echo "ERROR: hwmon device '$name' not found" >&2
25 return 1
26 }
27
28 FAN_HWMON=$(find_hwmon "gpdfan")
29 TEMP_HWMON=$(find_hwmon "k10temp")
30
31 PWM_FILE="$FAN_HWMON/pwm1"
32 PWM_ENABLE="$FAN_HWMON/pwm1_enable"
33 TEMP_FILE="$TEMP_HWMON/temp1_input"
34
35 echo "Fan control: $PWM_FILE"
36 echo "Temperature: $TEMP_FILE"
37
38 # Enable manual PWM control
39 echo 1 > "$PWM_ENABLE"
40
41 cleanup() {
42 echo "Setting fan to 0..."
43 echo 0 > "$PWM_FILE" 2>/dev/null || true
44 }
45 trap cleanup EXIT
46
47 while true; do
48 TEMP=$(cat "$TEMP_FILE")
49
50 if (( TEMP <= MINTEMP )); then
51 PWM=$MINPWM
52 elif (( TEMP >= MAXTEMP )); then
53 PWM=$MAXPWM
54 else
55 # Linear interpolation
56 PWM=$(( (TEMP - MINTEMP) * (MAXPWM - MINPWM) / (MAXTEMP - MINTEMP) + MINPWM ))
57 fi
58
59 echo "$PWM" > "$PWM_FILE"
60 sleep "$INTERVAL"
61 done
62 '';
63in
64{
65 boot.kernelModules = [
66 "gpd_fan"
67 "k10temp"
68 ];
69
70 # Disable the built-in fancontrol (it uses brittle hwmon numbers)
71 hardware.fancontrol.enable = false;
72
73 # Stop fan service and set PWM to 0 before s2idle, restart after resume
74 environment.etc."systemd/system-sleep/gpd-fan".source = pkgs.writeShellScript "gpd-fan-sleep" ''
75 find_hwmon() {
76 for hwmon in /sys/class/hwmon/hwmon*; do
77 if [ -f "$hwmon/name" ] && [ "$(cat "$hwmon/name")" = "$1" ]; then
78 echo "$hwmon"
79 return 0
80 fi
81 done
82 return 1
83 }
84 case "$1" in
85 pre)
86 # Stop the fan service first so it can't overwrite our PWM 0
87 systemctl stop gpd-fan-control.service
88 FAN=$(find_hwmon gpdfan)
89 if [ -n "$FAN" ]; then
90 echo 1 > "$FAN/pwm1_enable"
91 echo 0 > "$FAN/pwm1"
92 fi
93 ;;
94 post)
95 systemctl start gpd-fan-control.service
96 ;;
97 esac
98 '';
99
100 systemd.services.gpd-fan-control = {
101 description = "GPD Fan Control (dynamic hwmon discovery)";
102 wantedBy = [ "multi-user.target" ];
103 after = [ "systemd-modules-load.service" ];
104 serviceConfig = {
105 ExecStart = gpd-fan-control;
106 Restart = "always";
107 RestartSec = 5;
108 };
109 };
110
111}