Smooth fan speed changes (#190)
* SMOOTH_FANS, SMOOTH_FANS_UP, SMOOTH_FANS_DOWN build flags to smooth fan speed changes. Defaults 40, set SMOOTH_FANS=0 to disable and keep sharp fan speed changes * fix for ACPI CPU temperature * allow for a floor to be set for fan smoothing and specifically configure oryp6/7 to start smoothing at 25% to mitigate fan buzzing below 25% * update default config values for fans * update all devices to use defaults for heatup, cooldown, update galp5 fan curves * Decrease default cooldown time from 20 to 10 Co-authored-by: Jacob Kauffmann <jacob@system76.com>
This commit is contained in:
parent
b7368e8202
commit
8ea0403850
@ -29,8 +29,6 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
@ -41,8 +39,6 @@ CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
|
||||
# Enable DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
|
@ -29,8 +29,6 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
@ -41,8 +39,6 @@ CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
|
||||
# Enable DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
|
@ -29,8 +29,6 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
@ -41,8 +39,6 @@ CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
|
||||
# Enable DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
|
@ -94,7 +94,7 @@ uint8_t acpi_read(uint8_t addr) {
|
||||
}
|
||||
break;
|
||||
|
||||
ACPI_8(0x07, peci_temp >> 6);
|
||||
ACPI_8(0x07, peci_temp);
|
||||
|
||||
// Handle AC adapter and battery present
|
||||
case 0x10:
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#if HAVE_DGPU
|
||||
|
||||
#include <board/fan.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/peci.h>
|
||||
#include <board/power.h>
|
||||
@ -16,7 +15,7 @@
|
||||
|
||||
// Fan speed is the lowest requested over HEATUP seconds
|
||||
#ifndef BOARD_DGPU_HEATUP
|
||||
#define BOARD_DGPU_HEATUP 10
|
||||
#define BOARD_DGPU_HEATUP 4
|
||||
#endif
|
||||
|
||||
static uint8_t FAN_HEATUP[BOARD_DGPU_HEATUP] = { 0 };
|
||||
@ -54,7 +53,7 @@ static struct Fan __code FAN = {
|
||||
.heatup_size = ARRAY_SIZE(FAN_HEATUP),
|
||||
.cooldown = FAN_COOLDOWN,
|
||||
.cooldown_size = ARRAY_SIZE(FAN_COOLDOWN),
|
||||
.interpolate = false,
|
||||
.interpolate = SMOOTH_FANS != 0,
|
||||
};
|
||||
|
||||
void dgpu_init(void) {
|
||||
|
@ -4,15 +4,20 @@
|
||||
#include <common/debug.h>
|
||||
#include <ec/pwm.h>
|
||||
|
||||
bool fan_max = false;
|
||||
|
||||
#define max_speed PWM_DUTY(100)
|
||||
#define min_speed PWM_DUTY(0)
|
||||
|
||||
#ifndef SYNC_FANS
|
||||
#define SYNC_FANS 1
|
||||
#if SMOOTH_FANS != 0
|
||||
static const uint8_t max_jump_up = (MAX_FAN_SPEED - MIN_FAN_SPEED) / (uint8_t) SMOOTH_FANS_UP;
|
||||
static const uint8_t max_jump_down = (MAX_FAN_SPEED - MIN_FAN_SPEED) / (uint8_t) SMOOTH_FANS_DOWN;
|
||||
#else
|
||||
static const uint8_t max_jump_up = MAX_FAN_SPEED - MIN_FAN_SPEED;
|
||||
static const uint8_t max_jump_down = MAX_FAN_SPEED - MIN_FAN_SPEED;
|
||||
#endif
|
||||
|
||||
static const uint8_t min_speed_to_smooth = PWM_DUTY(SMOOTH_FANS_MIN);
|
||||
|
||||
bool fan_max = false;
|
||||
uint8_t last_duty_dgpu = 0;
|
||||
uint8_t last_duty_peci = 0;
|
||||
|
||||
void fan_reset(void) {
|
||||
// Do not manually set fans to maximum speed
|
||||
fan_max = false;
|
||||
@ -30,7 +35,7 @@ uint8_t fan_duty(const struct Fan * fan, int16_t temp) __reentrant {
|
||||
} else if (temp < cur->temp) {
|
||||
// If lower than first temp, return 0%
|
||||
if (i == 0) {
|
||||
return min_speed;
|
||||
return MIN_FAN_SPEED;
|
||||
} else {
|
||||
const struct FanPoint * prev = &fan->points[i - 1];
|
||||
|
||||
@ -52,26 +57,30 @@ uint8_t fan_duty(const struct Fan * fan, int16_t temp) __reentrant {
|
||||
}
|
||||
|
||||
// If no point is found, return 100%
|
||||
return max_speed;
|
||||
return MAX_FAN_SPEED;
|
||||
}
|
||||
|
||||
void fan_duty_set(uint8_t peci_fan_duty, uint8_t dgpu_fan_duty) __reentrant {
|
||||
#if SYNC_FANS != 0
|
||||
peci_fan_duty = peci_fan_duty > dgpu_fan_duty ? peci_fan_duty : dgpu_fan_duty;
|
||||
dgpu_fan_duty = peci_fan_duty > dgpu_fan_duty ? peci_fan_duty : dgpu_fan_duty;
|
||||
#endif
|
||||
#if SYNC_FANS != 0
|
||||
peci_fan_duty = peci_fan_duty > dgpu_fan_duty ? peci_fan_duty : dgpu_fan_duty;
|
||||
dgpu_fan_duty = peci_fan_duty > dgpu_fan_duty ? peci_fan_duty : dgpu_fan_duty;
|
||||
#endif
|
||||
|
||||
// set PECI fan duty
|
||||
if (peci_fan_duty != DCR2) {
|
||||
DCR2 = peci_fan_duty;
|
||||
DEBUG("PECI fan_duty=%d\n", peci_fan_duty);
|
||||
}
|
||||
// set PECI fan duty
|
||||
if (peci_fan_duty != DCR2) {
|
||||
DEBUG("PECI fan_duty_raw=%d\n", peci_fan_duty);
|
||||
last_duty_peci = peci_fan_duty = fan_smooth(last_duty_peci, peci_fan_duty);
|
||||
DCR2 = fan_max ? MAX_FAN_SPEED : peci_fan_duty;
|
||||
DEBUG("PECI fan_duty_smoothed=%d\n", peci_fan_duty);
|
||||
}
|
||||
|
||||
// set dGPU fan duty
|
||||
if (dgpu_fan_duty != DCR4) {
|
||||
DCR4 = dgpu_fan_duty;
|
||||
DEBUG("DGPU fan_duty=%d\n", dgpu_fan_duty);
|
||||
}
|
||||
// set dGPU fan duty
|
||||
if (dgpu_fan_duty != DCR4) {
|
||||
DEBUG("DGPU fan_duty_raw=%d\n", dgpu_fan_duty);
|
||||
last_duty_dgpu = dgpu_fan_duty = fan_smooth(last_duty_dgpu, dgpu_fan_duty);
|
||||
DCR4 = fan_max ? MAX_FAN_SPEED : dgpu_fan_duty;
|
||||
DEBUG("DGPU fan_duty_smoothed=%d\n", dgpu_fan_duty);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t fan_heatup(const struct Fan * fan, uint8_t duty) __reentrant {
|
||||
@ -105,3 +114,35 @@ uint8_t fan_cooldown(const struct Fan * fan, uint8_t duty) __reentrant {
|
||||
|
||||
return highest;
|
||||
}
|
||||
|
||||
uint8_t fan_smooth(uint8_t last_duty, uint8_t duty) __reentrant {
|
||||
uint8_t next_duty = duty;
|
||||
|
||||
// ramping down
|
||||
if (duty < last_duty) {
|
||||
// out of bounds (lower) safeguard
|
||||
uint8_t smoothed = last_duty < MIN_FAN_SPEED + max_jump_down
|
||||
? MIN_FAN_SPEED
|
||||
: last_duty - max_jump_down;
|
||||
|
||||
// use smoothed value if above min and if smoothed is closer than raw
|
||||
if (last_duty > min_speed_to_smooth && smoothed > duty) {
|
||||
next_duty = smoothed;
|
||||
}
|
||||
}
|
||||
|
||||
// ramping up
|
||||
if (duty > last_duty) {
|
||||
// out of bounds (higher) safeguard
|
||||
uint8_t smoothed = last_duty > MAX_FAN_SPEED - max_jump_up
|
||||
? MAX_FAN_SPEED
|
||||
: last_duty + max_jump_up;
|
||||
|
||||
// use smoothed value if above min and if smoothed is closer than raw
|
||||
if (duty > min_speed_to_smooth && smoothed < duty) {
|
||||
next_duty = smoothed;
|
||||
}
|
||||
}
|
||||
|
||||
return next_duty;
|
||||
}
|
||||
|
@ -7,6 +7,29 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define PWM_DUTY(X) ((uint8_t)(((((uint16_t)(X)) * 255) + 99) / 100))
|
||||
#define MAX_FAN_SPEED PWM_DUTY(100)
|
||||
#define MIN_FAN_SPEED PWM_DUTY(0)
|
||||
|
||||
#ifndef SMOOTH_FANS
|
||||
#define SMOOTH_FANS 1 // default to fan smoothing
|
||||
#endif
|
||||
|
||||
#ifndef SYNC_FANS
|
||||
#define SYNC_FANS 1 // default to syncing fan speeds
|
||||
#endif
|
||||
|
||||
#if SMOOTH_FANS != 0
|
||||
#ifndef SMOOTH_FANS_UP
|
||||
#define SMOOTH_FANS_UP 45 // default to ~11 seconds for full ramp-up
|
||||
#endif
|
||||
#ifndef SMOOTH_FANS_DOWN
|
||||
#define SMOOTH_FANS_DOWN 100 // default to ~25 seconds for full ramp-down
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SMOOTH_FANS_MIN
|
||||
#define SMOOTH_FANS_MIN 0 // default to smoothing all fan speed changes
|
||||
#endif
|
||||
|
||||
struct FanPoint {
|
||||
int16_t temp;
|
||||
@ -31,5 +54,6 @@ uint8_t fan_duty(const struct Fan * fan, int16_t temp) __reentrant;
|
||||
void fan_duty_set(uint8_t peci_fan_duty, uint8_t dgpu_fan_duty) __reentrant;
|
||||
uint8_t fan_heatup(const struct Fan * fan, uint8_t duty) __reentrant;
|
||||
uint8_t fan_cooldown(const struct Fan * fan, uint8_t duty) __reentrant;
|
||||
uint8_t fan_smooth(uint8_t last_duty, uint8_t duty) __reentrant;
|
||||
|
||||
#endif // _BOARD_FAN_H
|
||||
|
@ -43,6 +43,10 @@ void serial(void) __interrupt(4) {}
|
||||
void timer_2(void) __interrupt(5) {}
|
||||
|
||||
uint8_t main_cycle = 0;
|
||||
const uint16_t battery_interval = 1000;
|
||||
// update fan speed more frequently for smoother fans
|
||||
// NOTE: event loop is longer than 100ms and maybe even longer than 250
|
||||
const uint16_t fan_interval = SMOOTH_FANS != 0 ? 250 : 1000;
|
||||
|
||||
void init(void) {
|
||||
// Must happen first
|
||||
@ -91,7 +95,9 @@ void main(void) {
|
||||
|
||||
INFO("System76 EC board '%s', version '%s'\n", board(), version());
|
||||
|
||||
uint32_t last_time = 0;
|
||||
uint32_t last_time_battery = 0;
|
||||
uint32_t last_time_fan = 0;
|
||||
|
||||
for(main_cycle = 0; ; main_cycle++) {
|
||||
switch (main_cycle % 3) {
|
||||
case 0:
|
||||
@ -115,12 +121,17 @@ void main(void) {
|
||||
|
||||
if (main_cycle == 0) {
|
||||
uint32_t time = time_get();
|
||||
// Only run the following once a second
|
||||
if (last_time > time || (time - last_time) >= 1000) {
|
||||
last_time = time;
|
||||
// Only run the following once per interval
|
||||
if (last_time_fan > time || (time - last_time_fan) >= fan_interval) {
|
||||
last_time_fan = time;
|
||||
|
||||
// Update fan speeds
|
||||
fan_duty_set(peci_get_fan_duty(), dgpu_get_fan_duty());
|
||||
}
|
||||
|
||||
// Only run the following once per interval
|
||||
if (last_time_battery > time || (time - last_time_battery) >= battery_interval) {
|
||||
last_time_battery = time;
|
||||
|
||||
// Updates battery status
|
||||
battery_event();
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
// Fan speed is the lowest requested over HEATUP seconds
|
||||
#ifndef BOARD_HEATUP
|
||||
#define BOARD_HEATUP 10
|
||||
#define BOARD_HEATUP 4
|
||||
#endif
|
||||
|
||||
static uint8_t FAN_HEATUP[BOARD_HEATUP] = { 0 };
|
||||
@ -30,7 +30,7 @@ static uint8_t FAN_COOLDOWN[BOARD_COOLDOWN] = { 0 };
|
||||
bool peci_on = false;
|
||||
int16_t peci_temp = 0;
|
||||
|
||||
#define PECI_TEMP(X) (((int16_t)(X)) << 6)
|
||||
#define PECI_TEMP(X) ((int16_t)(X))
|
||||
|
||||
#define FAN_POINT(T, D) { .temp = PECI_TEMP(T), .duty = PWM_DUTY(D) }
|
||||
|
||||
@ -54,7 +54,7 @@ static struct Fan __code FAN = {
|
||||
.heatup_size = ARRAY_SIZE(FAN_HEATUP),
|
||||
.cooldown = FAN_COOLDOWN,
|
||||
.cooldown_size = ARRAY_SIZE(FAN_COOLDOWN),
|
||||
.interpolate = false,
|
||||
.interpolate = SMOOTH_FANS != 0,
|
||||
};
|
||||
|
||||
void peci_init(void) {
|
||||
@ -156,7 +156,7 @@ uint8_t peci_get_fan_duty(void) {
|
||||
// Use result if finished successfully
|
||||
uint8_t low = HORDDR;
|
||||
uint8_t high = HORDDR;
|
||||
uint16_t peci_offset = ((int16_t)high << 8) | (int16_t)low;
|
||||
uint16_t peci_offset = (((int16_t)high << 8) | (int16_t)low) >> 6;
|
||||
|
||||
peci_temp = PECI_TEMP(T_JUNCTION) + peci_offset;
|
||||
duty = fan_duty(&FAN, peci_temp);
|
||||
|
@ -35,23 +35,19 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(70, 40), \
|
||||
FAN_POINT(75, 60), \
|
||||
FAN_POINT(80, 75), \
|
||||
FAN_POINT(85, 90), \
|
||||
FAN_POINT(90, 100) \
|
||||
FAN_POINT(70, 25), \
|
||||
FAN_POINT(80, 25), \
|
||||
FAN_POINT(80, 40), \
|
||||
FAN_POINT(88, 40), \
|
||||
FAN_POINT(88, 100) \
|
||||
"
|
||||
|
||||
# DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(70, 40), \
|
||||
FAN_POINT(75, 60), \
|
||||
FAN_POINT(70, 25), \
|
||||
FAN_POINT(75, 40), \
|
||||
FAN_POINT(80, 75), \
|
||||
FAN_POINT(85, 90), \
|
||||
FAN_POINT(90, 100) \
|
||||
|
@ -29,8 +29,6 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
@ -41,8 +39,6 @@ CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
|
||||
# Enable DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
|
@ -30,8 +30,6 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
@ -42,8 +40,6 @@ CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
|
||||
# Enable DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(60, 40), \
|
||||
FAN_POINT(65, 60), \
|
||||
|
@ -28,9 +28,10 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_AC=180 \
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Don't smooth fan speed changes below 25% to mitigate buzzing
|
||||
CFLAGS+=-DSMOOTH_FANS_MIN=25
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(55, 25), \
|
||||
FAN_POINT(65, 30), \
|
||||
@ -43,8 +44,6 @@ CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
|
||||
# Enable DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(55, 25), \
|
||||
FAN_POINT(65, 30), \
|
||||
|
@ -28,9 +28,10 @@ CFLAGS+=\
|
||||
-DPOWER_LIMIT_AC=180 \
|
||||
-DPOWER_LIMIT_DC=28
|
||||
|
||||
# Don't smooth fan speed changes below 25% to mitigate buzzing
|
||||
CFLAGS+=-DSMOOTH_FANS_MIN=25
|
||||
|
||||
# Custom fan curve
|
||||
CFLAGS+=-DBOARD_HEATUP=5
|
||||
CFLAGS+=-DBOARD_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
FAN_POINT(55, 25), \
|
||||
FAN_POINT(65, 30), \
|
||||
@ -43,8 +44,6 @@ CFLAGS+=-DBOARD_FAN_POINTS="\
|
||||
|
||||
# Enable DGPU support
|
||||
CFLAGS+=-DHAVE_DGPU=1
|
||||
CFLAGS+=-DBOARD_DGPU_HEATUP=5
|
||||
CFLAGS+=-DBOARD_DGPU_COOLDOWN=20
|
||||
CFLAGS+=-DBOARD_DGPU_FAN_POINTS="\
|
||||
FAN_POINT(55, 25), \
|
||||
FAN_POINT(65, 30), \
|
||||
|
Loading…
x
Reference in New Issue
Block a user