diff options
Diffstat (limited to 'drivers/platform/x86/hp-wmi.c')
| -rw-r--r-- | drivers/platform/x86/hp-wmi.c | 101 | 
1 files changed, 94 insertions, 7 deletions
| diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index e94e59283ecb..027a1467d009 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -21,6 +21,7 @@  #include <linux/input.h>  #include <linux/input/sparse-keymap.h>  #include <linux/platform_device.h> +#include <linux/platform_profile.h>  #include <linux/acpi.h>  #include <linux/rfkill.h>  #include <linux/string.h> @@ -85,7 +86,7 @@ enum hp_wmi_commandtype {  	HPWMI_FEATURE2_QUERY		= 0x0d,  	HPWMI_WIRELESS2_QUERY		= 0x1b,  	HPWMI_POSTCODEERROR_QUERY	= 0x2a, -	HPWMI_THERMAL_POLICY_QUERY	= 0x4c, +	HPWMI_THERMAL_PROFILE_QUERY	= 0x4c,  };  enum hp_wmi_command { @@ -119,6 +120,12 @@ enum hp_wireless2_bits {  	HPWMI_POWER_FW_OR_HW	= HPWMI_POWER_BIOS | HPWMI_POWER_HARD,  }; +enum hp_thermal_profile { +	HP_THERMAL_PROFILE_PERFORMANCE	= 0x00, +	HP_THERMAL_PROFILE_DEFAULT		= 0x01, +	HP_THERMAL_PROFILE_COOL			= 0x02 +}; +  #define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW)  #define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT) @@ -159,6 +166,8 @@ static const struct key_entry hp_wmi_keymap[] = {  static struct input_dev *hp_wmi_input_dev;  static struct platform_device *hp_wmi_platform_dev; +static struct platform_profile_handler platform_profile_handler; +static bool platform_profile_support;  static struct rfkill *wifi_rfkill;  static struct rfkill *bluetooth_rfkill; @@ -869,23 +878,98 @@ fail:  	return err;  } -static int thermal_policy_setup(struct platform_device *device) +static int thermal_profile_get(void) +{ +	return hp_wmi_read_int(HPWMI_THERMAL_PROFILE_QUERY); +} + +static int thermal_profile_set(int thermal_profile) +{ +	return hp_wmi_perform_query(HPWMI_THERMAL_PROFILE_QUERY, HPWMI_WRITE, &thermal_profile, +							   sizeof(thermal_profile), 0); +} + +static int platform_profile_get(struct platform_profile_handler *pprof, +				enum platform_profile_option *profile) +{ +	int tp; + +	tp = thermal_profile_get(); +	if (tp < 0) +		return tp; + +	switch (tp) { +	case HP_THERMAL_PROFILE_PERFORMANCE: +		*profile =  PLATFORM_PROFILE_PERFORMANCE; +		break; +	case HP_THERMAL_PROFILE_DEFAULT: +		*profile =  PLATFORM_PROFILE_BALANCED; +		break; +	case HP_THERMAL_PROFILE_COOL: +		*profile =  PLATFORM_PROFILE_COOL; +		break; +	default: +		return -EINVAL; +	} + +	return 0; +} + +static int platform_profile_set(struct platform_profile_handler *pprof, +				enum platform_profile_option profile)  {  	int err, tp; -	tp = hp_wmi_read_int(HPWMI_THERMAL_POLICY_QUERY); +	switch (profile) { +	case PLATFORM_PROFILE_PERFORMANCE: +		tp =  HP_THERMAL_PROFILE_PERFORMANCE; +		break; +	case PLATFORM_PROFILE_BALANCED: +		tp =  HP_THERMAL_PROFILE_DEFAULT; +		break; +	case PLATFORM_PROFILE_COOL: +		tp =  HP_THERMAL_PROFILE_COOL; +		break; +	default: +		return -EOPNOTSUPP; +	} + +	err = thermal_profile_set(tp); +	if (err) +		return err; + +	return 0; +} + +static int thermal_profile_setup(void) +{ +	int err, tp; + +	tp = thermal_profile_get();  	if (tp < 0)  		return tp;  	/* -	 * call thermal policy write command to ensure that the firmware correctly +	 * call thermal profile write command to ensure that the firmware correctly  	 * sets the OEM variables for the DPTF  	 */ -	err = hp_wmi_perform_query(HPWMI_THERMAL_POLICY_QUERY, HPWMI_WRITE, &tp, -							   sizeof(tp), 0); +	err = thermal_profile_set(tp);  	if (err)  		return err; +	platform_profile_handler.profile_get = platform_profile_get, +	platform_profile_handler.profile_set = platform_profile_set, + +	set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); +	set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices); +	set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices); + +	err = platform_profile_register(&platform_profile_handler); +	if (err) +		return err; + +	platform_profile_support = true; +  	return 0;  } @@ -900,7 +984,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)  	if (hp_wmi_rfkill_setup(device))  		hp_wmi_rfkill2_setup(device); -	thermal_policy_setup(device); +	thermal_profile_setup();  	return 0;  } @@ -927,6 +1011,9 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)  		rfkill_destroy(wwan_rfkill);  	} +	if (platform_profile_support) +		platform_profile_remove(); +  	return 0;  } | 
