Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add manual fan control #512

Merged
merged 2 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/board/system76/common/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ uint8_t acpi_read(uint8_t addr) {
ACPI_16(0xD2, fan2_rpm);
#endif // FAN2_PWM

case 0xD4:
data = fan_get_mode();
break;

#if HAVE_LED_AIRPLANE_N
// Airplane mode LED
case 0xD9:
Expand Down Expand Up @@ -224,6 +228,29 @@ void acpi_write(uint8_t addr, uint8_t data) {
(void)battery_save_thresholds();
break;

case 0xCE:
if (fan_get_mode() == FAN_MODE_PWM) {
fan1_pwm_target = data;
}
break;

#ifdef FAN2_PWM
case 0xCF:
if (fan_get_mode() == FAN_MODE_PWM) {
fan2_pwm_target = data;
}
break;
#endif

case 0xD4:
switch (data) {
case FAN_MODE_AUTO:
case FAN_MODE_PWM:
fan_set_mode(data);
break;
}
break;

#if HAVE_LED_AIRPLANE_N
// Airplane mode LED
case 0xD9:
Expand Down
9 changes: 9 additions & 0 deletions src/board/system76/common/fan.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#endif

bool fan_max = false;
static enum FanMode fan_mode = FAN_MODE_AUTO;

uint8_t fan1_pwm_actual = 0;
uint8_t fan1_pwm_target = 0;
Expand Down Expand Up @@ -261,3 +262,11 @@ void fan_update_duty(void) {
fan2_rpm = fan_get_tach1_rpm();
#endif
}

enum FanMode fan_get_mode(void) {
return fan_mode;
}

void fan_set_mode(enum FanMode mode) {
fan_mode = mode;
}
12 changes: 12 additions & 0 deletions src/board/system76/common/include/board/fan.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ struct Fan {
uint8_t pwm_min;
};

enum FanMode {
// EC control
FAN_MODE_AUTO = 0,
// Host control via target PWM
FAN_MODE_PWM = 1,
// Host control via target RPM
FAN_MODE_RPM = 2,
};

extern bool fan_max;

extern uint8_t fan1_pwm_actual;
Expand All @@ -34,4 +43,7 @@ void fan_reset(void);
void fan_update_duty(void);
void fan_update_target(void);

enum FanMode fan_get_mode(void);
void fan_set_mode(enum FanMode);

#endif // _BOARD_FAN_H
5 changes: 4 additions & 1 deletion src/board/system76/common/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,10 @@ void main(void) {
last_time_1sec = time;

battery_event();
fan_update_target();

if (fan_get_mode() == FAN_MODE_AUTO) {
fan_update_target();
}
}

// Idle until next timer interrupt
Expand Down
41 changes: 35 additions & 6 deletions src/board/system76/common/smfi.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static enum Result cmd_print(void) {
return RES_OK;
}

static enum Result cmd_fan_get(void) {
static enum Result cmd_fan_get_pwm(void) {
switch (smfi_cmd[SMFI_CMD_DATA]) {
case 1:
smfi_cmd[SMFI_CMD_DATA + 1] = fan1_pwm_actual;
Expand All @@ -139,7 +139,11 @@ static enum Result cmd_fan_get(void) {
return RES_ERR;
}

static enum Result cmd_fan_set(void) {
static enum Result cmd_fan_set_pwm(void) {
if (fan_get_mode() != FAN_MODE_PWM) {
return RES_ERR;
}

switch (smfi_cmd[SMFI_CMD_DATA]) {
case 1:
// Set duty cycle of FAN1
Expand All @@ -157,6 +161,24 @@ static enum Result cmd_fan_set(void) {
return RES_ERR;
}

static enum Result cmd_fan_get_mode(void) {
smfi_cmd[SMFI_CMD_DATA] = fan_get_mode();
return RES_OK;
}

static enum Result cmd_fan_set_mode(void) {
enum FanMode mode = smfi_cmd[SMFI_CMD_DATA];

switch (mode) {
case FAN_MODE_AUTO:
case FAN_MODE_PWM:
fan_set_mode(mode);
return RES_OK;
}

return RES_ERR;
}

static enum Result cmd_keymap_get(void) {
int16_t layer = smfi_cmd[SMFI_CMD_DATA];
int16_t output = smfi_cmd[SMFI_CMD_DATA + 1];
Expand Down Expand Up @@ -384,11 +406,11 @@ void smfi_event(void) {
case CMD_PRINT:
smfi_cmd[SMFI_CMD_RES] = cmd_print();
break;
case CMD_FAN_GET:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_get();
case CMD_FAN_GET_PWM:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_get_pwm();
break;
case CMD_FAN_SET:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_set();
case CMD_FAN_SET_PWM:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_set_pwm();
break;
case CMD_KEYMAP_GET:
smfi_cmd[SMFI_CMD_RES] = cmd_keymap_get();
Expand Down Expand Up @@ -421,6 +443,13 @@ void smfi_event(void) {
break;
#endif // CONFIG_SECURITY

case CMD_FAN_GET_MODE:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_get_mode();
break;
case CMD_FAN_SET_MODE:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_set_mode();
break;

#endif // !defined(__SCRATCH__)
case CMD_SPI:
smfi_cmd[SMFI_CMD_RES] = cmd_spi();
Expand Down
13 changes: 8 additions & 5 deletions src/common/include/common/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ enum Command {
CMD_SPI = 5,
// Reset EC
CMD_RESET = 6,
// Get fan speeds
CMD_FAN_GET = 7,
// Set fan speeds
CMD_FAN_SET = 8,
// Get fan PWM duty
CMD_FAN_GET_PWM = 7,
// Set fan PWM duty
CMD_FAN_SET_PWM = 8,
// Get keyboard map index
CMD_KEYMAP_GET = 9,
// Set keyboard map index
Expand All @@ -50,7 +50,10 @@ enum Command {
CMD_SECURITY_GET = 20,
// Set security state
CMD_SECURITY_SET = 21,
//TODO
// Get fan control mode
CMD_FAN_GET_MODE = 22,
// Set fan control mode
CMD_FAN_SET_MODE = 23,
};

enum Result {
Expand Down
64 changes: 58 additions & 6 deletions tool/src/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, vec};
use core::convert::TryFrom;
use core::fmt;

use crate::{Access, Error, Spi, SpiTarget};

Expand All @@ -16,8 +17,8 @@ enum Cmd {
Print = 4,
Spi = 5,
Reset = 6,
FanGet = 7,
FanSet = 8,
FanGetPwm = 7,
FanSetPwm = 8,
KeymapGet = 9,
KeymapSet = 10,
LedGetValue = 11,
Expand All @@ -31,6 +32,8 @@ enum Cmd {
SetNoInput = 19,
SecurityGet = 20,
SecuritySet = 21,
FanGetMode = 22,
FanSetMode = 23,
}

const CMD_SPI_FLAG_READ: u8 = 1 << 0;
Expand Down Expand Up @@ -65,6 +68,42 @@ impl TryFrom<u8> for SecurityState {
}
}

#[derive(Clone, Copy, Default, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
#[repr(u8)]
pub enum FanMode {
/// EC control
#[default]
Auto = 0,
/// Host control via target PWM
Pwm = 1,
/// Host control via target RPM
Rpm = 2,
}

impl fmt::Display for FanMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Auto => write!(f, "auto"),
Self::Pwm => write!(f, "pwm"),
Self::Rpm => write!(f, "rpm"),
}
}
}

impl TryFrom<u8> for FanMode {
type Error = Error;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Auto),
1 => Ok(Self::Pwm),
2 => Ok(Self::Rpm),
_ => Err(Error::Verify),
}
}
}

/// Run EC commands using a provided access method
pub struct Ec<A: Access> {
access: A,
Expand Down Expand Up @@ -176,16 +215,16 @@ impl<A: Access> Ec<A> {
}

/// Read fan duty cycle by fan index
pub unsafe fn fan_get(&mut self, index: u8) -> Result<u8, Error> {
pub unsafe fn fan_get_pwm(&mut self, index: u8) -> Result<u8, Error> {
let mut data = [index, 0];
self.command(Cmd::FanGet, &mut data)?;
self.command(Cmd::FanGetPwm, &mut data)?;
Ok(data[1])
}

/// Set fan duty cycle by fan index
pub unsafe fn fan_set(&mut self, index: u8, duty: u8) -> Result<(), Error> {
pub unsafe fn fan_set_pwm(&mut self, index: u8, duty: u8) -> Result<(), Error> {
let mut data = [index, duty];
self.command(Cmd::FanSet, &mut data)
self.command(Cmd::FanSetPwm, &mut data)
}

/// Read keymap data by layout, output pin, and input pin
Expand Down Expand Up @@ -275,6 +314,19 @@ impl<A: Access> Ec<A> {
self.command(Cmd::SecuritySet, &mut data)
}

/// Get fan control mode.
pub unsafe fn fan_get_mode(&mut self) -> Result<FanMode, Error> {
let mut data = [0];
self.command(Cmd::FanGetMode, &mut data)?;
FanMode::try_from(data[0])
}

/// Set fan control mode.
pub unsafe fn fan_set_mode(&mut self, mode: FanMode) -> Result<(), Error> {
let mut data = [mode as u8];
self.command(Cmd::FanSetMode, &mut data)
}

pub fn into_dyn(self) -> Ec<Box<dyn Access>>
where
A: 'static,
Expand Down
2 changes: 1 addition & 1 deletion tool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern crate alloc;
pub use self::access::*;
mod access;

pub use self::ec::{Ec, SecurityState};
pub use self::ec::{Ec, FanMode, SecurityState};
mod ec;

pub use self::error::Error;
Expand Down
Loading
Loading