145 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env bash
 | 
						|
 | 
						|
set -e
 | 
						|
 | 
						|
bail() {
 | 
						|
    echo "Error: $@" >&2
 | 
						|
    echo "Exiting..." >&2
 | 
						|
    exit 1
 | 
						|
}
 | 
						|
 | 
						|
map_range() {
 | 
						|
    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
 | 
						|
 | 
						|
    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_MIN="$2"
 | 
						|
    TEMP_MAX="$3"
 | 
						|
 | 
						|
    PWM_MIN_PCT="$4"
 | 
						|
    PWM_MAX_PCT="$5"
 | 
						|
}
 | 
						|
 | 
						|
validate_variables() {
 | 
						|
    if ! [ -d "$HWMON" ]; then
 | 
						|
        bail "Invalid drm-device: '$HWMON' is not a directory"
 | 
						|
    fi
 | 
						|
 | 
						|
    if ! [ -f "$TEMP_INPUT" ]; then
 | 
						|
        bail "Error: Could not find hotspot temperature at '$TEMP_INPUT'"
 | 
						|
    fi
 | 
						|
 | 
						|
    if [ -z "$TEMP_MIN" -o -z "$TEMP_MAX" -o -z "$PWM_MIN_PCT" -o -z "$PWM_MAX_PCT" ];then
 | 
						|
        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
 | 
						|
 | 
						|
    if test -n "$AMDGPU_FAN_CRONTROL_DEBUG"; then
 | 
						|
        echo "TEMP_MIN=$TEMP_MIN°C" >&2
 | 
						|
        echo "TEMP_MAX=$TEMP_MAX°C" >&2
 | 
						|
        echo "FAN_MIN=$PWM_MIN_PCT% (PWM=$PWM_MIN)" >&2
 | 
						|
        echo "FAN_MAX=$PWM_MAX_PCT% (PWM=$PWM_MAX)" >&2
 | 
						|
    fi
 | 
						|
 | 
						|
    # Set fan control mode to manual, this will be reverted in the cleanup trap
 | 
						|
    echo 1 > "$HWMON/pwm1_enable"
 | 
						|
 | 
						|
    PREV_PWM=0
 | 
						|
}
 | 
						|
 | 
						|
main_loop() {
 | 
						|
    TEMPERATURE_RAW=$(cat "$TEMP_INPUT")
 | 
						|
    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
 | 
						|
        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 "$@"
 |