diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 22f51e4..874f89c 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "../clevo_interfaces.h" #include "../uniwill_interfaces.h" #include "tuxedo_io_ioctl.h" @@ -50,8 +52,21 @@ static u32 clevo_identify(void) return clevo_get_active_interface_id(NULL) == 0 ? 1 : 0; } +static bool uniwill_tdp_config_two; +static bool uniwill_tdp_config_three; + static u32 uniwill_identify(void) { + // Device check for two configurable TDPs + uniwill_tdp_config_two = false +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) + || dmi_match(DMI_PRODUCT_SKU, "0001") +#endif + ; + + // Device check for three configurable TDPs + uniwill_tdp_config_three = false; + return uniwill_get_active_interface_id(NULL) == 0 ? 1 : 0; } @@ -203,6 +218,45 @@ static u32 uw_set_fan_auto(void) return 0; } +static int uw_get_tdp(u8 tdp_index) +{ + u8 tdp_data; + u16 tdp_base_addr = 0x0783; + u16 tdp_current_addr = tdp_base_addr + tdp_index; + bool has_current_setting = false; + + if (tdp_index < 2 && uniwill_tdp_config_two) + has_current_setting = true; + else if (tdp_index < 3 && uniwill_tdp_config_three) + has_current_setting = true; + + if (!has_current_setting) + return -1; + + uniwill_read_ec_ram(tdp_current_addr, &tdp_data); + + return tdp_data; +} + +static int uw_set_tdp(u8 tdp_index, u8 tdp_data) +{ + u16 tdp_base_addr = 0x0783; + u16 tdp_current_addr = tdp_base_addr + tdp_index; + bool has_current_setting = false; + + if (tdp_index < 2 && uniwill_tdp_config_two) + has_current_setting = true; + else if (tdp_index < 3 && uniwill_tdp_config_three) + has_current_setting = true; + + if (!has_current_setting) + return -1; + + uniwill_write_ec_ram(tdp_current_addr, tdp_data); + + return 0; +} + static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigned long arg) { u32 result = 0; @@ -261,6 +315,19 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne result = byte_data; copy_result = copy_to_user((void *) arg, &result, sizeof(result)); break; + case R_UW_TDP0: + result = uw_get_tdp(0); + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_TDP1: + result = uw_get_tdp(1); + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_TDP2: + result = uw_get_tdp(2); + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + #ifdef DEBUG case R_TF_BC: copy_result = copy_from_user(&uw_arg, (void *) arg, sizeof(uw_arg)); @@ -304,6 +371,18 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne case W_UW_FANAUTO: uw_set_fan_auto(); break; + case W_UW_TDP0: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + uw_set_tdp(0, argument); + break; + case W_UW_TDP1: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + uw_set_tdp(1, argument); + break; + case W_UW_TDP2: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + uw_set_tdp(2, argument); + break; #ifdef DEBUG case W_TF_BC: reg_write_return.dword = 0; diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h index f63fb7f..e177fe1 100644 --- a/src/tuxedo_io/tuxedo_io_ioctl.h +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -80,6 +80,10 @@ #define R_UW_MODE _IOR(MAGIC_READ_UW, 0x14, int32_t*) #define R_UW_MODE_ENABLE _IOR(MAGIC_READ_UW, 0x15, int32_t*) +#define R_UW_TDP0 _IOR(MAGIC_READ_UW, 0x16, int32_t*) +#define R_UW_TDP1 _IOR(MAGIC_READ_UW, 0x17, int32_t*) +#define R_UW_TDP2 _IOR(MAGIC_READ_UW, 0x18, int32_t*) + // Write #define W_UW_FANSPEED _IOW(MAGIC_WRITE_UW, 0x10, int32_t*) #define W_UW_FANSPEED2 _IOW(MAGIC_WRITE_UW, 0x11, int32_t*) @@ -87,4 +91,8 @@ #define W_UW_MODE_ENABLE _IOW(MAGIC_WRITE_UW, 0x13, int32_t*) #define W_UW_FANAUTO _IO(MAGIC_WRITE_UW, 0x14) // undo all previous calls of W_UW_FANSPEED and W_UW_FANSPEED2 +#define W_UW_TDP0 _IOW(MAGIC_WRITE_UW, 0x15, int32_t*) +#define W_UW_TDP1 _IOW(MAGIC_WRITE_UW, 0x16, int32_t*) +#define W_UW_TDP2 _IOW(MAGIC_WRITE_UW, 0x17, int32_t*) + #endif