This repository has no description
2.1 kB
83 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 "Restoring automatic fan control..."
43 echo 0 > "$PWM_ENABLE" 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 systemd.services.gpd-fan-control = {
74 description = "GPD Fan Control (dynamic hwmon discovery)";
75 wantedBy = [ "multi-user.target" ];
76 after = [ "systemd-modules-load.service" ];
77 serviceConfig = {
78 ExecStart = gpd-fan-control;
79 Restart = "always";
80 RestartSec = 5;
81 };
82 };
83}