diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h index ebe7396..084ff96 100644 --- a/src/tuxedo_io/tongfang_wmi.h +++ b/src/tuxedo_io/tongfang_wmi.h @@ -289,3 +289,40 @@ static void uniwill_exit(void) // Disable manual mode uw_ec_write_addr(0x41, 0x07, 0x00, 0x00, ®_write_return); } + +static u32 uw_set_fan(u32 fan_index, u8 fan_speed) +{ + u8 reg_low, reg_high = 0x18; + u32 i; + union uw_ec_read_return reg_read_return; + union uw_ec_write_return reg_write_return; + u8 low_reg_fan0 = 0x04; + u8 low_reg_fan1 = 0x09; + + if (fan_index == 0) + reg_low = low_reg_fan0; + else if (fan_index == 1) + reg_low = low_reg_fan1; + else + return -EINVAL; + + // Check current mode + uw_ec_read_addr(0x51, 0x07, ®_read_return); + if (reg_read_return.bytes.data_low != 0x40) { + // If not "full fan mode" (ie. 0x40) switch to it (required for fancontrol) + uw_ec_write_addr(0x51, 0x07, 0x40, 0x00, ®_write_return); + // Attempt to write both fans as quick as possible before complete ramp-up + pr_debug("prevent ramp-up start\n"); + for (i = 0; i < 10; ++i) { + uw_ec_write_addr(low_reg_fan0, reg_high, fan_speed & 0xff, 0x00, ®_write_return); + uw_ec_write_addr(low_reg_fan1, reg_high, fan_speed & 0xff, 0x00, ®_write_return); + msleep(10); + } + pr_debug("prevent ramp-up done\n"); + } else { + // Otherwise just set the chosen fan + uw_ec_write_addr(reg_low, reg_high, fan_speed & 0xff, 0x00, ®_write_return); + } + + return 0; +} diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 064b715..daff5d8 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -211,28 +211,12 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne case W_UW_FANSPEED: // Get fan speed argument copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); - - // Check current mode - uw_ec_read_addr(0x51, 0x07, ®_read_return); - if (reg_read_return.bytes.data_low != 0x40) { - // If not "full fan mode" (ie. 0x40) switch to it (required for fancontrol) - uw_ec_write_addr(0x51, 0x07, 0x40, 0x00, ®_write_return); - } - // Set speed - uw_ec_write_addr(0x04, 0x18, argument & 0xff, 0x00, ®_write_return); + uw_set_fan(0, argument); break; case W_UW_FANSPEED2: // Get fan speed argument copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); - - // Check current mode - uw_ec_read_addr(0x51, 0x07, ®_read_return); - if (reg_read_return.bytes.data_low != 0x40) { - // If not "full fan mode" (ie. 0x40) switch to it (required for fancontrol) - uw_ec_write_addr(0x51, 0x07, 0x40, 0x00, ®_write_return); - } - // Set speed - uw_ec_write_addr(0x09, 0x18, argument & 0xff, 0x00, ®_write_return); + uw_set_fan(1, argument); break; case W_UW_MODE: copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument));