amdgpu: refactor fan controller
This commit is contained in:
parent
2057831d36
commit
be8d98d6f4
1 changed files with 126 additions and 67 deletions
|
@ -2,85 +2,144 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
DEVICE="$1" # eg: /sys/class/drm/card1/device
|
|
||||||
HWMON=$(echo "$DEVICE"/hwmon/hwmon*)
|
|
||||||
|
|
||||||
exit() {
|
|
||||||
echo "Setting controll to auto" >&2
|
|
||||||
echo 2 > "$HWMON/pwm1_enable"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap exit EXIT INT
|
|
||||||
|
|
||||||
bail() {
|
bail() {
|
||||||
echo "Error: $@" >&2
|
echo "Error: $@" >&2
|
||||||
echo "Exiting..." >&2
|
echo "Exiting..." >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ! [ -d "$HWMON" ]; then
|
map_range() {
|
||||||
bail "Invalid HWMON"
|
VALUE="$1"
|
||||||
|
MIN_INPUT="$2"
|
||||||
|
MAX_INPUT="$3"
|
||||||
|
INPUT_RANGE=$(( $MAX_INPUT - $MIN_INPUT ))
|
||||||
|
MIN_OUTPUT="$4"
|
||||||
|
MAX_OUTPUT="$5"
|
||||||
|
OUTPUT_RANGE=$(( $MAX_OUTPUT - $MIN_OUTPUT ))
|
||||||
|
|
||||||
|
echo $(( ($VALUE - $MIN_INPUT) * $OUTPUT_RANGE / $INPUT_RANGE + $MIN_OUTPUT ))
|
||||||
|
}
|
||||||
|
|
||||||
|
clamp() {
|
||||||
|
VALUE="$1"
|
||||||
|
|
||||||
|
MIN="$2"
|
||||||
|
MAX="$3"
|
||||||
|
|
||||||
|
VALUE=$VALUE
|
||||||
|
if [ "$VALUE" -gt $MAX ]; then
|
||||||
|
VALUE=$MAX
|
||||||
|
elif [ "$VALUE" -lt $MIN ]; then
|
||||||
|
VALUE=$MIN
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo $VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
echo "Setting controll to auto" >&2
|
||||||
|
if test -f "$HWMON/pwm1_enable"; then
|
||||||
|
echo 2 > "$HWMON/pwm1_enable"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT INT
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 <device> <min-temp> <max-temp> <min-fan> <max-fan>" >&2
|
||||||
|
echo "Example: $0 /sys/class/drm/card1/device 60 100 10 80" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_cli() {
|
||||||
|
if test -n "$AMDGPU_FAN_CRONTROL_DEBUG"; then
|
||||||
|
echo parse_cli "$@" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEVICE="$1" # eg: /sys/class/drm/card1/device
|
||||||
|
HWMON=$(echo "$DEVICE"/hwmon/hwmon*)
|
||||||
TEMP_INPUT="$HWMON/temp2_input"
|
TEMP_INPUT="$HWMON/temp2_input"
|
||||||
|
|
||||||
if ! [ -f $TEMP_INPUT ]; then
|
|
||||||
bail "Invalid TEMP_INPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
TEMP_MIN="$2"
|
TEMP_MIN="$2"
|
||||||
TEMP_MAX="$3"
|
TEMP_MAX="$3"
|
||||||
|
|
||||||
if [ -z "$TEMP_MIN" ];then
|
|
||||||
bail "No minimum temperature provided"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$TEMP_MAX" ];then
|
|
||||||
bail "No maximum temperature provided"
|
|
||||||
fi
|
|
||||||
|
|
||||||
PWM_MIN_PCT="$4"
|
PWM_MIN_PCT="$4"
|
||||||
PWM_MAX_PCT="$5"
|
PWM_MAX_PCT="$5"
|
||||||
|
}
|
||||||
|
|
||||||
if [ -z "$PWM_MIN_PCT" ];then
|
validate_variables() {
|
||||||
bail "No minimum fan speed % not provided"
|
if ! [ -d "$HWMON" ]; then
|
||||||
|
bail "Invalid drm-device: '$HWMON' is not a directory"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$PWM_MAX_PCT" ];then
|
if ! [ -f "$TEMP_INPUT" ]; then
|
||||||
bail "No maximum fan speed % not provided"
|
bail "Error: Could not find hotspot temperature at '$TEMP_INPUT'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PWM_MIN="$(( $PWM_MIN_PCT * 255 / 100))"
|
if [ -z "$TEMP_MIN" -o -z "$TEMP_MAX" -o -z "$PWM_MIN_PCT" -o -z "$PWM_MAX_PCT" ];then
|
||||||
PWM_MAX="$(( $PWM_MAX_PCT * 255 / 100))"
|
usage
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
PWM_MIN=$(map_range $PWM_MIN_PCT 0 100 0 255)
|
||||||
|
PWM_MAX=$(map_range $PWM_MAX_PCT 0 100 0 255)
|
||||||
|
|
||||||
echo "Running..." >&2
|
echo "Running..." >&2
|
||||||
|
|
||||||
echo "TEMP_MIN=$TEMP_MIN°C"
|
if test -n "$AMDGPU_FAN_CRONTROL_DEBUG"; then
|
||||||
echo "TEMP_MAX=$TEMP_MAX°C"
|
echo "TEMP_MIN=$TEMP_MIN°C" >&2
|
||||||
echo "FAN_MIN=$PWM_MIN_PCT%"
|
echo "TEMP_MAX=$TEMP_MAX°C" >&2
|
||||||
echo "FAN_MAX=$PWM_MAX_PCT%"
|
echo "FAN_MIN=$PWM_MIN_PCT% (PWM=$PWM_MIN)" >&2
|
||||||
|
echo "FAN_MAX=$PWM_MAX_PCT% (PWM=$PWM_MAX)" >&2
|
||||||
echo 1 > "$HWMON/pwm1_enable"
|
|
||||||
|
|
||||||
PREV=0
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
TEMPERATURE_RAW=$(cat "$TEMP_INPUT")
|
|
||||||
TEMPERATURE="$(( $TEMPERATURE_RAW / 1000 ))"
|
|
||||||
# Remap from a number between 60_000..90_000 to 0..255
|
|
||||||
PWM=$(( ($TEMPERATURE - $TEMP_MIN) * $PWM_MAX / ($TEMP_MAX - $TEMP_MIN) ))
|
|
||||||
|
|
||||||
if [ "$PWM" -gt $PWM_MAX ]; then
|
|
||||||
PWM=$PWM_MAX
|
|
||||||
elif [ "$PWM" -lt $PWM_MIN ]; then
|
|
||||||
PWM=$PWM_MIN
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AVG="$(( ($PWM * 20 + $PREV * 80) / 100 ))"
|
# Set fan control mode to manual, this will be reverted in the cleanup trap
|
||||||
|
echo 1 > "$HWMON/pwm1_enable"
|
||||||
|
|
||||||
echo "$AVG"
|
PREV_PWM=0
|
||||||
|
}
|
||||||
|
|
||||||
echo "$AVG" > "$HWMON/pwm1"
|
main_loop() {
|
||||||
PREV="$AVG"
|
TEMPERATURE_RAW=$(cat "$TEMP_INPUT")
|
||||||
sleep .1s
|
TEMPERATURE="$(( $TEMPERATURE_RAW / 1000 ))" # 60_000 = 60°C
|
||||||
|
|
||||||
|
# Calculate the fan speed we would want to reach given infinite time
|
||||||
|
TARGET_PWM=$(map_range $TEMPERATURE $TEMP_MIN $TEMP_MAX $PWM_MIN $PWM_MAX)
|
||||||
|
|
||||||
|
# Calculate an appropriate amount to "walk" in the direction of target fan speed
|
||||||
|
DIFFERENCE=$(( $TARGET_PWM - $PREV_PWM ))
|
||||||
|
ADJUSTMENT=$(( $DIFFERENCE * 20 / 100 ))
|
||||||
|
|
||||||
|
NEXT_PWM=$(( $PREV_PWM + $ADJUSTMENT ))
|
||||||
|
|
||||||
|
NEXT_PWM=$(clamp $NEXT_PWM $PWM_MIN $PWM_MAX)
|
||||||
|
NEXT_PWM_PCT=$(map_range $NEXT_PWM 0 255 0 100 )
|
||||||
|
|
||||||
|
if test -n "$AMDGPU_FAN_CRONTROL_DEBUG"; then
|
||||||
|
for var in \
|
||||||
|
"Temperature=$TEMPERATURE°C" \
|
||||||
|
"Fan speed=$NEXT_PWM_PCT%" \
|
||||||
|
; do
|
||||||
|
echo -en "$var\t"
|
||||||
done
|
done
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apply the new fan speed
|
||||||
|
echo "$NEXT_PWM" > "$HWMON/pwm1"
|
||||||
|
|
||||||
|
# Wait for next iteratino
|
||||||
|
PREV_PWM="$NEXT_PWM"
|
||||||
|
sleep .1s
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
parse_cli "$@"
|
||||||
|
validate_variables
|
||||||
|
setup
|
||||||
|
while true; do
|
||||||
|
main_loop
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue