Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
Note: File does not exist in v4.6.
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * HP WMI hotkeys
   4 *
   5 * Copyright (C) 2008 Red Hat <mjg@redhat.com>
   6 * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
   7 *
   8 * Portions based on wistron_btns.c:
   9 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
  10 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
  11 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
  12 */
  13
  14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/init.h>
  19#include <linux/slab.h>
  20#include <linux/types.h>
  21#include <linux/input.h>
  22#include <linux/input/sparse-keymap.h>
  23#include <linux/platform_device.h>
  24#include <linux/platform_profile.h>
  25#include <linux/hwmon.h>
  26#include <linux/acpi.h>
  27#include <linux/mutex.h>
  28#include <linux/cleanup.h>
  29#include <linux/power_supply.h>
  30#include <linux/rfkill.h>
  31#include <linux/string.h>
  32#include <linux/dmi.h>
  33
  34MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>");
  35MODULE_DESCRIPTION("HP laptop WMI driver");
  36MODULE_LICENSE("GPL");
  37
  38MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
  39MODULE_ALIAS("wmi:5FB7F034-2C63-45E9-BE91-3D44E2C707E4");
  40
  41#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
  42#define HPWMI_BIOS_GUID "5FB7F034-2C63-45E9-BE91-3D44E2C707E4"
  43
  44#define HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET 0x62
  45#define HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET 0x63
  46#define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95
  47
  48#define ACPI_AC_CLASS "ac_adapter"
  49
  50#define zero_if_sup(tmp) (zero_insize_support?0:sizeof(tmp)) // use when zero insize is required
  51
  52/* DMI board names of devices that should use the omen specific path for
  53 * thermal profiles.
  54 * This was obtained by taking a look in the windows omen command center
  55 * app and parsing a json file that they use to figure out what capabilities
  56 * the device should have.
  57 * A device is considered an omen if the DisplayName in that list contains
  58 * "OMEN", and it can use the thermal profile stuff if the "Feature" array
  59 * contains "PerformanceControl".
  60 */
  61static const char * const omen_thermal_profile_boards[] = {
  62	"84DA", "84DB", "84DC", "8574", "8575", "860A", "87B5", "8572", "8573",
  63	"8600", "8601", "8602", "8605", "8606", "8607", "8746", "8747", "8749",
  64	"874A", "8603", "8604", "8748", "886B", "886C", "878A", "878B", "878C",
  65	"88C8", "88CB", "8786", "8787", "8788", "88D1", "88D2", "88F4", "88FD",
  66	"88F5", "88F6", "88F7", "88FE", "88FF", "8900", "8901", "8902", "8912",
  67	"8917", "8918", "8949", "894A", "89EB", "8BAD", "8A42", "8A15"
  68};
  69
  70/* DMI Board names of Omen laptops that are specifically set to be thermal
  71 * profile version 0 by the Omen Command Center app, regardless of what
  72 * the get system design information WMI call returns
  73 */
  74static const char * const omen_thermal_profile_force_v0_boards[] = {
  75	"8607", "8746", "8747", "8749", "874A", "8748"
  76};
  77
  78/* DMI board names of Omen laptops that have a thermal profile timer which will
  79 * cause the embedded controller to set the thermal profile back to
  80 * "balanced" when reaching zero.
  81 */
  82static const char * const omen_timed_thermal_profile_boards[] = {
  83	"8BAD", "8A42", "8A15"
  84};
  85
  86/* DMI Board names of Victus laptops */
  87static const char * const victus_thermal_profile_boards[] = {
  88	"8A25"
  89};
  90
  91enum hp_wmi_radio {
  92	HPWMI_WIFI	= 0x0,
  93	HPWMI_BLUETOOTH	= 0x1,
  94	HPWMI_WWAN	= 0x2,
  95	HPWMI_GPS	= 0x3,
  96};
  97
  98enum hp_wmi_event_ids {
  99	HPWMI_DOCK_EVENT		= 0x01,
 100	HPWMI_PARK_HDD			= 0x02,
 101	HPWMI_SMART_ADAPTER		= 0x03,
 102	HPWMI_BEZEL_BUTTON		= 0x04,
 103	HPWMI_WIRELESS			= 0x05,
 104	HPWMI_CPU_BATTERY_THROTTLE	= 0x06,
 105	HPWMI_LOCK_SWITCH		= 0x07,
 106	HPWMI_LID_SWITCH		= 0x08,
 107	HPWMI_SCREEN_ROTATION		= 0x09,
 108	HPWMI_COOLSENSE_SYSTEM_MOBILE	= 0x0A,
 109	HPWMI_COOLSENSE_SYSTEM_HOT	= 0x0B,
 110	HPWMI_PROXIMITY_SENSOR		= 0x0C,
 111	HPWMI_BACKLIT_KB_BRIGHTNESS	= 0x0D,
 112	HPWMI_PEAKSHIFT_PERIOD		= 0x0F,
 113	HPWMI_BATTERY_CHARGE_PERIOD	= 0x10,
 114	HPWMI_SANITIZATION_MODE		= 0x17,
 115	HPWMI_CAMERA_TOGGLE		= 0x1A,
 116	HPWMI_OMEN_KEY			= 0x1D,
 117	HPWMI_SMART_EXPERIENCE_APP	= 0x21,
 118};
 119
 120/*
 121 * struct bios_args buffer is dynamically allocated.  New WMI command types
 122 * were introduced that exceeds 128-byte data size.  Changes to handle
 123 * the data size allocation scheme were kept in hp_wmi_perform_qurey function.
 124 */
 125struct bios_args {
 126	u32 signature;
 127	u32 command;
 128	u32 commandtype;
 129	u32 datasize;
 130	u8 data[];
 131};
 132
 133enum hp_wmi_commandtype {
 134	HPWMI_DISPLAY_QUERY		= 0x01,
 135	HPWMI_HDDTEMP_QUERY		= 0x02,
 136	HPWMI_ALS_QUERY			= 0x03,
 137	HPWMI_HARDWARE_QUERY		= 0x04,
 138	HPWMI_WIRELESS_QUERY		= 0x05,
 139	HPWMI_BATTERY_QUERY		= 0x07,
 140	HPWMI_BIOS_QUERY		= 0x09,
 141	HPWMI_FEATURE_QUERY		= 0x0b,
 142	HPWMI_HOTKEY_QUERY		= 0x0c,
 143	HPWMI_FEATURE2_QUERY		= 0x0d,
 144	HPWMI_WIRELESS2_QUERY		= 0x1b,
 145	HPWMI_POSTCODEERROR_QUERY	= 0x2a,
 146	HPWMI_SYSTEM_DEVICE_MODE	= 0x40,
 147	HPWMI_THERMAL_PROFILE_QUERY	= 0x4c,
 148};
 149
 150enum hp_wmi_gm_commandtype {
 151	HPWMI_FAN_SPEED_GET_QUERY = 0x11,
 152	HPWMI_SET_PERFORMANCE_MODE = 0x1A,
 153	HPWMI_FAN_SPEED_MAX_GET_QUERY = 0x26,
 154	HPWMI_FAN_SPEED_MAX_SET_QUERY = 0x27,
 155	HPWMI_GET_SYSTEM_DESIGN_DATA = 0x28,
 156};
 157
 158enum hp_wmi_command {
 159	HPWMI_READ	= 0x01,
 160	HPWMI_WRITE	= 0x02,
 161	HPWMI_ODM	= 0x03,
 162	HPWMI_GM	= 0x20008,
 163};
 164
 165enum hp_wmi_hardware_mask {
 166	HPWMI_DOCK_MASK		= 0x01,
 167	HPWMI_TABLET_MASK	= 0x04,
 168};
 169
 170struct bios_return {
 171	u32 sigpass;
 172	u32 return_code;
 173};
 174
 175enum hp_return_value {
 176	HPWMI_RET_WRONG_SIGNATURE	= 0x02,
 177	HPWMI_RET_UNKNOWN_COMMAND	= 0x03,
 178	HPWMI_RET_UNKNOWN_CMDTYPE	= 0x04,
 179	HPWMI_RET_INVALID_PARAMETERS	= 0x05,
 180};
 181
 182enum hp_wireless2_bits {
 183	HPWMI_POWER_STATE	= 0x01,
 184	HPWMI_POWER_SOFT	= 0x02,
 185	HPWMI_POWER_BIOS	= 0x04,
 186	HPWMI_POWER_HARD	= 0x08,
 187	HPWMI_POWER_FW_OR_HW	= HPWMI_POWER_BIOS | HPWMI_POWER_HARD,
 188};
 189
 190enum hp_thermal_profile_omen_v0 {
 191	HP_OMEN_V0_THERMAL_PROFILE_DEFAULT     = 0x00,
 192	HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE = 0x01,
 193	HP_OMEN_V0_THERMAL_PROFILE_COOL        = 0x02,
 194};
 195
 196enum hp_thermal_profile_omen_v1 {
 197	HP_OMEN_V1_THERMAL_PROFILE_DEFAULT	= 0x30,
 198	HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE	= 0x31,
 199	HP_OMEN_V1_THERMAL_PROFILE_COOL		= 0x50,
 200};
 201
 202enum hp_thermal_profile_omen_flags {
 203	HP_OMEN_EC_FLAGS_TURBO		= 0x04,
 204	HP_OMEN_EC_FLAGS_NOTIMER	= 0x02,
 205	HP_OMEN_EC_FLAGS_JUSTSET	= 0x01,
 206};
 207
 208enum hp_thermal_profile_victus {
 209	HP_VICTUS_THERMAL_PROFILE_DEFAULT		= 0x00,
 210	HP_VICTUS_THERMAL_PROFILE_PERFORMANCE		= 0x01,
 211	HP_VICTUS_THERMAL_PROFILE_QUIET			= 0x03,
 212};
 213
 214enum hp_thermal_profile {
 215	HP_THERMAL_PROFILE_PERFORMANCE	= 0x00,
 216	HP_THERMAL_PROFILE_DEFAULT		= 0x01,
 217	HP_THERMAL_PROFILE_COOL			= 0x02,
 218	HP_THERMAL_PROFILE_QUIET		= 0x03,
 219};
 220
 221#define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW)
 222#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
 223
 224struct bios_rfkill2_device_state {
 225	u8 radio_type;
 226	u8 bus_type;
 227	u16 vendor_id;
 228	u16 product_id;
 229	u16 subsys_vendor_id;
 230	u16 subsys_product_id;
 231	u8 rfkill_id;
 232	u8 power;
 233	u8 unknown[4];
 234};
 235
 236/* 7 devices fit into the 128 byte buffer */
 237#define HPWMI_MAX_RFKILL2_DEVICES	7
 238
 239struct bios_rfkill2_state {
 240	u8 unknown[7];
 241	u8 count;
 242	u8 pad[8];
 243	struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
 244};
 245
 246static const struct key_entry hp_wmi_keymap[] = {
 247	{ KE_KEY, 0x02,    { KEY_BRIGHTNESSUP } },
 248	{ KE_KEY, 0x03,    { KEY_BRIGHTNESSDOWN } },
 249	{ KE_KEY, 0x270,   { KEY_MICMUTE } },
 250	{ KE_KEY, 0x20e6,  { KEY_PROG1 } },
 251	{ KE_KEY, 0x20e8,  { KEY_MEDIA } },
 252	{ KE_KEY, 0x2142,  { KEY_MEDIA } },
 253	{ KE_KEY, 0x213b,  { KEY_INFO } },
 254	{ KE_KEY, 0x2169,  { KEY_ROTATE_DISPLAY } },
 255	{ KE_KEY, 0x216a,  { KEY_SETUP } },
 256	{ KE_IGNORE, 0x21a4,  }, /* Win Lock On */
 257	{ KE_IGNORE, 0x121a4, }, /* Win Lock Off */
 258	{ KE_KEY, 0x21a5,  { KEY_PROG2 } }, /* HP Omen Key */
 259	{ KE_KEY, 0x21a7,  { KEY_FN_ESC } },
 260	{ KE_KEY, 0x21a8,  { KEY_PROG2 } }, /* HP Envy x360 programmable key */
 261	{ KE_KEY, 0x21a9,  { KEY_TOUCHPAD_OFF } },
 262	{ KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } },
 263	{ KE_KEY, 0x231b,  { KEY_HELP } },
 264	{ KE_END, 0 }
 265};
 266
 267/*
 268 * Mutex for the active_platform_profile variable,
 269 * see omen_powersource_event.
 270 */
 271static DEFINE_MUTEX(active_platform_profile_lock);
 272
 273static struct input_dev *hp_wmi_input_dev;
 274static struct input_dev *camera_shutter_input_dev;
 275static struct platform_device *hp_wmi_platform_dev;
 276static struct platform_profile_handler platform_profile_handler;
 277static struct notifier_block platform_power_source_nb;
 278static enum platform_profile_option active_platform_profile;
 279static bool platform_profile_support;
 280static bool zero_insize_support;
 281
 282static struct rfkill *wifi_rfkill;
 283static struct rfkill *bluetooth_rfkill;
 284static struct rfkill *wwan_rfkill;
 285
 286struct rfkill2_device {
 287	u8 id;
 288	int num;
 289	struct rfkill *rfkill;
 290};
 291
 292static int rfkill2_count;
 293static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
 294
 295/*
 296 * Chassis Types values were obtained from SMBIOS reference
 297 * specification version 3.00. A complete list of system enclosures
 298 * and chassis types is available on Table 17.
 299 */
 300static const char * const tablet_chassis_types[] = {
 301	"30", /* Tablet*/
 302	"31", /* Convertible */
 303	"32"  /* Detachable */
 304};
 305
 306#define DEVICE_MODE_TABLET	0x06
 307
 308/* map output size to the corresponding WMI method id */
 309static inline int encode_outsize_for_pvsz(int outsize)
 310{
 311	if (outsize > 4096)
 312		return -EINVAL;
 313	if (outsize > 1024)
 314		return 5;
 315	if (outsize > 128)
 316		return 4;
 317	if (outsize > 4)
 318		return 3;
 319	if (outsize > 0)
 320		return 2;
 321	return 1;
 322}
 323
 324/*
 325 * hp_wmi_perform_query
 326 *
 327 * query:	The commandtype (enum hp_wmi_commandtype)
 328 * write:	The command (enum hp_wmi_command)
 329 * buffer:	Buffer used as input and/or output
 330 * insize:	Size of input buffer
 331 * outsize:	Size of output buffer
 332 *
 333 * returns zero on success
 334 *         an HP WMI query specific error code (which is positive)
 335 *         -EINVAL if the query was not successful at all
 336 *         -EINVAL if the output buffer size exceeds buffersize
 337 *
 338 * Note: The buffersize must at least be the maximum of the input and output
 339 *       size. E.g. Battery info query is defined to have 1 byte input
 340 *       and 128 byte output. The caller would do:
 341 *       buffer = kzalloc(128, GFP_KERNEL);
 342 *       ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128)
 343 */
 344static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
 345				void *buffer, int insize, int outsize)
 346{
 347	struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL };
 348	struct bios_return *bios_return;
 349	union acpi_object *obj = NULL;
 350	struct bios_args *args = NULL;
 351	int mid, actual_insize, actual_outsize;
 352	size_t bios_args_size;
 353	int ret;
 354
 355	mid = encode_outsize_for_pvsz(outsize);
 356	if (WARN_ON(mid < 0))
 357		return mid;
 358
 359	actual_insize = max(insize, 128);
 360	bios_args_size = struct_size(args, data, actual_insize);
 361	args = kmalloc(bios_args_size, GFP_KERNEL);
 362	if (!args)
 363		return -ENOMEM;
 364
 365	input.length = bios_args_size;
 366	input.pointer = args;
 367
 368	args->signature = 0x55434553;
 369	args->command = command;
 370	args->commandtype = query;
 371	args->datasize = insize;
 372	memcpy(args->data, buffer, flex_array_size(args, data, insize));
 373
 374	ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
 375	if (ret)
 376		goto out_free;
 377
 378	obj = output.pointer;
 379	if (!obj) {
 380		ret = -EINVAL;
 381		goto out_free;
 382	}
 383
 384	if (obj->type != ACPI_TYPE_BUFFER) {
 385		pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret);
 386		ret = -EINVAL;
 387		goto out_free;
 388	}
 389
 390	bios_return = (struct bios_return *)obj->buffer.pointer;
 391	ret = bios_return->return_code;
 392
 393	if (ret) {
 394		if (ret != HPWMI_RET_UNKNOWN_COMMAND &&
 395		    ret != HPWMI_RET_UNKNOWN_CMDTYPE)
 396			pr_warn("query 0x%x returned error 0x%x\n", query, ret);
 397		goto out_free;
 398	}
 399
 400	/* Ignore output data of zero size */
 401	if (!outsize)
 402		goto out_free;
 403
 404	actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
 405	memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
 406	memset(buffer + actual_outsize, 0, outsize - actual_outsize);
 407
 408out_free:
 409	kfree(obj);
 410	kfree(args);
 411	return ret;
 412}
 413
 414static int hp_wmi_get_fan_speed(int fan)
 415{
 416	u8 fsh, fsl;
 417	char fan_data[4] = { fan, 0, 0, 0 };
 418
 419	int ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_GET_QUERY, HPWMI_GM,
 420				       &fan_data, sizeof(char),
 421				       sizeof(fan_data));
 422
 423	if (ret != 0)
 424		return -EINVAL;
 425
 426	fsh = fan_data[2];
 427	fsl = fan_data[3];
 428
 429	return (fsh << 8) | fsl;
 430}
 431
 432static int hp_wmi_read_int(int query)
 433{
 434	int val = 0, ret;
 435
 436	ret = hp_wmi_perform_query(query, HPWMI_READ, &val,
 437				   zero_if_sup(val), sizeof(val));
 438
 439	if (ret)
 440		return ret < 0 ? ret : -EINVAL;
 441
 442	return val;
 443}
 444
 445static int hp_wmi_get_dock_state(void)
 446{
 447	int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY);
 448
 449	if (state < 0)
 450		return state;
 451
 452	return !!(state & HPWMI_DOCK_MASK);
 453}
 454
 455static int hp_wmi_get_tablet_mode(void)
 456{
 457	char system_device_mode[4] = { 0 };
 458	const char *chassis_type;
 459	bool tablet_found;
 460	int ret;
 461
 462	chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
 463	if (!chassis_type)
 464		return -ENODEV;
 465
 466	tablet_found = match_string(tablet_chassis_types,
 467				    ARRAY_SIZE(tablet_chassis_types),
 468				    chassis_type) >= 0;
 469	if (!tablet_found)
 470		return -ENODEV;
 471
 472	ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ,
 473				   system_device_mode, zero_if_sup(system_device_mode),
 474				   sizeof(system_device_mode));
 475	if (ret < 0)
 476		return ret;
 477
 478	return system_device_mode[0] == DEVICE_MODE_TABLET;
 479}
 480
 481static int omen_thermal_profile_set(int mode)
 482{
 483	/* The Omen Control Center actively sets the first byte of the buffer to
 484	 * 255, so let's mimic this behaviour to be as close as possible to
 485	 * the original software.
 486	 */
 487	char buffer[2] = {-1, mode};
 488	int ret;
 489
 490	ret = hp_wmi_perform_query(HPWMI_SET_PERFORMANCE_MODE, HPWMI_GM,
 491				   &buffer, sizeof(buffer), 0);
 492
 493	if (ret)
 494		return ret < 0 ? ret : -EINVAL;
 495
 496	return mode;
 497}
 498
 499static bool is_omen_thermal_profile(void)
 500{
 501	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
 502
 503	if (!board_name)
 504		return false;
 505
 506	return match_string(omen_thermal_profile_boards,
 507			    ARRAY_SIZE(omen_thermal_profile_boards),
 508			    board_name) >= 0;
 509}
 510
 511static int omen_get_thermal_policy_version(void)
 512{
 513	unsigned char buffer[8] = { 0 };
 514	int ret;
 515
 516	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
 517
 518	if (board_name) {
 519		int matches = match_string(omen_thermal_profile_force_v0_boards,
 520			ARRAY_SIZE(omen_thermal_profile_force_v0_boards),
 521			board_name);
 522		if (matches >= 0)
 523			return 0;
 524	}
 525
 526	ret = hp_wmi_perform_query(HPWMI_GET_SYSTEM_DESIGN_DATA, HPWMI_GM,
 527				   &buffer, sizeof(buffer), sizeof(buffer));
 528
 529	if (ret)
 530		return ret < 0 ? ret : -EINVAL;
 531
 532	return buffer[3];
 533}
 534
 535static int omen_thermal_profile_get(void)
 536{
 537	u8 data;
 538
 539	int ret = ec_read(HP_OMEN_EC_THERMAL_PROFILE_OFFSET, &data);
 540
 541	if (ret)
 542		return ret;
 543
 544	return data;
 545}
 546
 547static int hp_wmi_fan_speed_max_set(int enabled)
 548{
 549	int ret;
 550
 551	ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_SET_QUERY, HPWMI_GM,
 552				   &enabled, sizeof(enabled), 0);
 553
 554	if (ret)
 555		return ret < 0 ? ret : -EINVAL;
 556
 557	return enabled;
 558}
 559
 560static int hp_wmi_fan_speed_max_get(void)
 561{
 562	int val = 0, ret;
 563
 564	ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_GET_QUERY, HPWMI_GM,
 565				   &val, zero_if_sup(val), sizeof(val));
 566
 567	if (ret)
 568		return ret < 0 ? ret : -EINVAL;
 569
 570	return val;
 571}
 572
 573static int __init hp_wmi_bios_2008_later(void)
 574{
 575	int state = 0;
 576	int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state,
 577				       zero_if_sup(state), sizeof(state));
 578	if (!ret)
 579		return 1;
 580
 581	return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
 582}
 583
 584static int __init hp_wmi_bios_2009_later(void)
 585{
 586	u8 state[128];
 587	int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
 588				       zero_if_sup(state), sizeof(state));
 589	if (!ret)
 590		return 1;
 591
 592	return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
 593}
 594
 595static int __init hp_wmi_enable_hotkeys(void)
 596{
 597	int value = 0x6e;
 598	int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value,
 599				       sizeof(value), 0);
 600
 601	return ret <= 0 ? ret : -EINVAL;
 602}
 603
 604static int hp_wmi_set_block(void *data, bool blocked)
 605{
 606	enum hp_wmi_radio r = (long)data;
 607	int query = BIT(r + 8) | ((!blocked) << r);
 608	int ret;
 609
 610	ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE,
 611				   &query, sizeof(query), 0);
 612
 613	return ret <= 0 ? ret : -EINVAL;
 614}
 615
 616static const struct rfkill_ops hp_wmi_rfkill_ops = {
 617	.set_block = hp_wmi_set_block,
 618};
 619
 620static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
 621{
 622	int mask = 0x200 << (r * 8);
 623
 624	int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
 625
 626	/* TBD: Pass error */
 627	WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
 628
 629	return !(wireless & mask);
 630}
 631
 632static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
 633{
 634	int mask = 0x800 << (r * 8);
 635
 636	int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
 637
 638	/* TBD: Pass error */
 639	WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
 640
 641	return !(wireless & mask);
 642}
 643
 644static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
 645{
 646	int rfkill_id = (int)(long)data;
 647	char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
 648	int ret;
 649
 650	ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE,
 651				   buffer, sizeof(buffer), 0);
 652
 653	return ret <= 0 ? ret : -EINVAL;
 654}
 655
 656static const struct rfkill_ops hp_wmi_rfkill2_ops = {
 657	.set_block = hp_wmi_rfkill2_set_block,
 658};
 659
 660static int hp_wmi_rfkill2_refresh(void)
 661{
 662	struct bios_rfkill2_state state;
 663	int err, i;
 664
 665	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
 666				   zero_if_sup(state), sizeof(state));
 667	if (err)
 668		return err;
 669
 670	for (i = 0; i < rfkill2_count; i++) {
 671		int num = rfkill2[i].num;
 672		struct bios_rfkill2_device_state *devstate;
 673
 674		devstate = &state.device[num];
 675
 676		if (num >= state.count ||
 677		    devstate->rfkill_id != rfkill2[i].id) {
 678			pr_warn("power configuration of the wireless devices unexpectedly changed\n");
 679			continue;
 680		}
 681
 682		rfkill_set_states(rfkill2[i].rfkill,
 683				  IS_SWBLOCKED(devstate->power),
 684				  IS_HWBLOCKED(devstate->power));
 685	}
 686
 687	return 0;
 688}
 689
 690static ssize_t display_show(struct device *dev, struct device_attribute *attr,
 691			    char *buf)
 692{
 693	int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY);
 694
 695	if (value < 0)
 696		return value;
 697	return sysfs_emit(buf, "%d\n", value);
 698}
 699
 700static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr,
 701			    char *buf)
 702{
 703	int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY);
 704
 705	if (value < 0)
 706		return value;
 707	return sysfs_emit(buf, "%d\n", value);
 708}
 709
 710static ssize_t als_show(struct device *dev, struct device_attribute *attr,
 711			char *buf)
 712{
 713	int value = hp_wmi_read_int(HPWMI_ALS_QUERY);
 714
 715	if (value < 0)
 716		return value;
 717	return sysfs_emit(buf, "%d\n", value);
 718}
 719
 720static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
 721			 char *buf)
 722{
 723	int value = hp_wmi_get_dock_state();
 724
 725	if (value < 0)
 726		return value;
 727	return sysfs_emit(buf, "%d\n", value);
 728}
 729
 730static ssize_t tablet_show(struct device *dev, struct device_attribute *attr,
 731			   char *buf)
 732{
 733	int value = hp_wmi_get_tablet_mode();
 734
 735	if (value < 0)
 736		return value;
 737	return sysfs_emit(buf, "%d\n", value);
 738}
 739
 740static ssize_t postcode_show(struct device *dev, struct device_attribute *attr,
 741			     char *buf)
 742{
 743	/* Get the POST error code of previous boot failure. */
 744	int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY);
 745
 746	if (value < 0)
 747		return value;
 748	return sysfs_emit(buf, "0x%x\n", value);
 749}
 750
 751static ssize_t als_store(struct device *dev, struct device_attribute *attr,
 752			 const char *buf, size_t count)
 753{
 754	u32 tmp;
 755	int ret;
 756
 757	ret = kstrtou32(buf, 10, &tmp);
 758	if (ret)
 759		return ret;
 760
 761	ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
 762				       sizeof(tmp), 0);
 763	if (ret)
 764		return ret < 0 ? ret : -EINVAL;
 765
 766	return count;
 767}
 768
 769static ssize_t postcode_store(struct device *dev, struct device_attribute *attr,
 770			      const char *buf, size_t count)
 771{
 772	u32 tmp = 1;
 773	bool clear;
 774	int ret;
 775
 776	ret = kstrtobool(buf, &clear);
 777	if (ret)
 778		return ret;
 779
 780	if (clear == false)
 781		return -EINVAL;
 782
 783	/* Clear the POST error code. It is kept until cleared. */
 784	ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp,
 785				       sizeof(tmp), 0);
 786	if (ret)
 787		return ret < 0 ? ret : -EINVAL;
 788
 789	return count;
 790}
 791
 792static int camera_shutter_input_setup(void)
 793{
 794	int err;
 795
 796	camera_shutter_input_dev = input_allocate_device();
 797	if (!camera_shutter_input_dev)
 798		return -ENOMEM;
 799
 800	camera_shutter_input_dev->name = "HP WMI camera shutter";
 801	camera_shutter_input_dev->phys = "wmi/input1";
 802	camera_shutter_input_dev->id.bustype = BUS_HOST;
 803
 804	__set_bit(EV_SW, camera_shutter_input_dev->evbit);
 805	__set_bit(SW_CAMERA_LENS_COVER, camera_shutter_input_dev->swbit);
 806
 807	err = input_register_device(camera_shutter_input_dev);
 808	if (err)
 809		goto err_free_dev;
 810
 811	return 0;
 812
 813 err_free_dev:
 814	input_free_device(camera_shutter_input_dev);
 815	camera_shutter_input_dev = NULL;
 816	return err;
 817}
 818
 819static DEVICE_ATTR_RO(display);
 820static DEVICE_ATTR_RO(hddtemp);
 821static DEVICE_ATTR_RW(als);
 822static DEVICE_ATTR_RO(dock);
 823static DEVICE_ATTR_RO(tablet);
 824static DEVICE_ATTR_RW(postcode);
 825
 826static struct attribute *hp_wmi_attrs[] = {
 827	&dev_attr_display.attr,
 828	&dev_attr_hddtemp.attr,
 829	&dev_attr_als.attr,
 830	&dev_attr_dock.attr,
 831	&dev_attr_tablet.attr,
 832	&dev_attr_postcode.attr,
 833	NULL,
 834};
 835ATTRIBUTE_GROUPS(hp_wmi);
 836
 837static void hp_wmi_notify(union acpi_object *obj, void *context)
 838{
 839	u32 event_id, event_data;
 840	u32 *location;
 841	int key_code;
 842
 843	if (!obj)
 844		return;
 845	if (obj->type != ACPI_TYPE_BUFFER) {
 846		pr_info("Unknown response received %d\n", obj->type);
 847		return;
 848	}
 849
 850	/*
 851	 * Depending on ACPI version the concatenation of id and event data
 852	 * inside _WED function will result in a 8 or 16 byte buffer.
 853	 */
 854	location = (u32 *)obj->buffer.pointer;
 855	if (obj->buffer.length == 8) {
 856		event_id = *location;
 857		event_data = *(location + 1);
 858	} else if (obj->buffer.length == 16) {
 859		event_id = *location;
 860		event_data = *(location + 2);
 861	} else {
 862		pr_info("Unknown buffer length %d\n", obj->buffer.length);
 863		return;
 864	}
 865
 866	switch (event_id) {
 867	case HPWMI_DOCK_EVENT:
 868		if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
 869			input_report_switch(hp_wmi_input_dev, SW_DOCK,
 870					    hp_wmi_get_dock_state());
 871		if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
 872			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
 873					    hp_wmi_get_tablet_mode());
 874		input_sync(hp_wmi_input_dev);
 875		break;
 876	case HPWMI_PARK_HDD:
 877		break;
 878	case HPWMI_SMART_ADAPTER:
 879		break;
 880	case HPWMI_BEZEL_BUTTON:
 881		key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
 882		if (key_code < 0)
 883			break;
 884
 885		if (!sparse_keymap_report_event(hp_wmi_input_dev,
 886						key_code, 1, true))
 887			pr_info("Unknown key code - 0x%x\n", key_code);
 888		break;
 889	case HPWMI_OMEN_KEY:
 890		if (event_data) /* Only should be true for HP Omen */
 891			key_code = event_data;
 892		else
 893			key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
 894
 895		if (!sparse_keymap_report_event(hp_wmi_input_dev,
 896						key_code, 1, true))
 897			pr_info("Unknown key code - 0x%x\n", key_code);
 898		break;
 899	case HPWMI_WIRELESS:
 900		if (rfkill2_count) {
 901			hp_wmi_rfkill2_refresh();
 902			break;
 903		}
 904
 905		if (wifi_rfkill)
 906			rfkill_set_states(wifi_rfkill,
 907					  hp_wmi_get_sw_state(HPWMI_WIFI),
 908					  hp_wmi_get_hw_state(HPWMI_WIFI));
 909		if (bluetooth_rfkill)
 910			rfkill_set_states(bluetooth_rfkill,
 911					  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
 912					  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
 913		if (wwan_rfkill)
 914			rfkill_set_states(wwan_rfkill,
 915					  hp_wmi_get_sw_state(HPWMI_WWAN),
 916					  hp_wmi_get_hw_state(HPWMI_WWAN));
 917		break;
 918	case HPWMI_CPU_BATTERY_THROTTLE:
 919		pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
 920		break;
 921	case HPWMI_LOCK_SWITCH:
 922		break;
 923	case HPWMI_LID_SWITCH:
 924		break;
 925	case HPWMI_SCREEN_ROTATION:
 926		break;
 927	case HPWMI_COOLSENSE_SYSTEM_MOBILE:
 928		break;
 929	case HPWMI_COOLSENSE_SYSTEM_HOT:
 930		break;
 931	case HPWMI_PROXIMITY_SENSOR:
 932		break;
 933	case HPWMI_BACKLIT_KB_BRIGHTNESS:
 934		break;
 935	case HPWMI_PEAKSHIFT_PERIOD:
 936		break;
 937	case HPWMI_BATTERY_CHARGE_PERIOD:
 938		break;
 939	case HPWMI_SANITIZATION_MODE:
 940		break;
 941	case HPWMI_CAMERA_TOGGLE:
 942		if (!camera_shutter_input_dev)
 943			if (camera_shutter_input_setup()) {
 944				pr_err("Failed to setup camera shutter input device\n");
 945				break;
 946			}
 947		if (event_data == 0xff)
 948			input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 1);
 949		else if (event_data == 0xfe)
 950			input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 0);
 951		else
 952			pr_warn("Unknown camera shutter state - 0x%x\n", event_data);
 953		input_sync(camera_shutter_input_dev);
 954		break;
 955	case HPWMI_SMART_EXPERIENCE_APP:
 956		break;
 957	default:
 958		pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
 959		break;
 960	}
 961}
 962
 963static int __init hp_wmi_input_setup(void)
 964{
 965	acpi_status status;
 966	int err, val;
 967
 968	hp_wmi_input_dev = input_allocate_device();
 969	if (!hp_wmi_input_dev)
 970		return -ENOMEM;
 971
 972	hp_wmi_input_dev->name = "HP WMI hotkeys";
 973	hp_wmi_input_dev->phys = "wmi/input0";
 974	hp_wmi_input_dev->id.bustype = BUS_HOST;
 975
 976	__set_bit(EV_SW, hp_wmi_input_dev->evbit);
 977
 978	/* Dock */
 979	val = hp_wmi_get_dock_state();
 980	if (!(val < 0)) {
 981		__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
 982		input_report_switch(hp_wmi_input_dev, SW_DOCK, val);
 983	}
 984
 985	/* Tablet mode */
 986	val = hp_wmi_get_tablet_mode();
 987	if (!(val < 0)) {
 988		__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
 989		input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
 990	}
 991
 992	err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
 993	if (err)
 994		goto err_free_dev;
 995
 996	/* Set initial hardware state */
 997	input_sync(hp_wmi_input_dev);
 998
 999	if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later())
1000		hp_wmi_enable_hotkeys();
1001
1002	status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
1003	if (ACPI_FAILURE(status)) {
1004		err = -EIO;
1005		goto err_free_dev;
1006	}
1007
1008	err = input_register_device(hp_wmi_input_dev);
1009	if (err)
1010		goto err_uninstall_notifier;
1011
1012	return 0;
1013
1014 err_uninstall_notifier:
1015	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
1016 err_free_dev:
1017	input_free_device(hp_wmi_input_dev);
1018	return err;
1019}
1020
1021static void hp_wmi_input_destroy(void)
1022{
1023	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
1024	input_unregister_device(hp_wmi_input_dev);
1025}
1026
1027static int __init hp_wmi_rfkill_setup(struct platform_device *device)
1028{
1029	int err, wireless;
1030
1031	wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
1032	if (wireless < 0)
1033		return wireless;
1034
1035	err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless,
1036				   sizeof(wireless), 0);
1037	if (err)
1038		return err;
1039
1040	if (wireless & 0x1) {
1041		wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
1042					   RFKILL_TYPE_WLAN,
1043					   &hp_wmi_rfkill_ops,
1044					   (void *) HPWMI_WIFI);
1045		if (!wifi_rfkill)
1046			return -ENOMEM;
1047		rfkill_init_sw_state(wifi_rfkill,
1048				     hp_wmi_get_sw_state(HPWMI_WIFI));
1049		rfkill_set_hw_state(wifi_rfkill,
1050				    hp_wmi_get_hw_state(HPWMI_WIFI));
1051		err = rfkill_register(wifi_rfkill);
1052		if (err)
1053			goto register_wifi_error;
1054	}
1055
1056	if (wireless & 0x2) {
1057		bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
1058						RFKILL_TYPE_BLUETOOTH,
1059						&hp_wmi_rfkill_ops,
1060						(void *) HPWMI_BLUETOOTH);
1061		if (!bluetooth_rfkill) {
1062			err = -ENOMEM;
1063			goto register_bluetooth_error;
1064		}
1065		rfkill_init_sw_state(bluetooth_rfkill,
1066				     hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
1067		rfkill_set_hw_state(bluetooth_rfkill,
1068				    hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
1069		err = rfkill_register(bluetooth_rfkill);
1070		if (err)
1071			goto register_bluetooth_error;
1072	}
1073
1074	if (wireless & 0x4) {
1075		wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
1076					   RFKILL_TYPE_WWAN,
1077					   &hp_wmi_rfkill_ops,
1078					   (void *) HPWMI_WWAN);
1079		if (!wwan_rfkill) {
1080			err = -ENOMEM;
1081			goto register_wwan_error;
1082		}
1083		rfkill_init_sw_state(wwan_rfkill,
1084				     hp_wmi_get_sw_state(HPWMI_WWAN));
1085		rfkill_set_hw_state(wwan_rfkill,
1086				    hp_wmi_get_hw_state(HPWMI_WWAN));
1087		err = rfkill_register(wwan_rfkill);
1088		if (err)
1089			goto register_wwan_error;
1090	}
1091
1092	return 0;
1093
1094register_wwan_error:
1095	rfkill_destroy(wwan_rfkill);
1096	wwan_rfkill = NULL;
1097	if (bluetooth_rfkill)
1098		rfkill_unregister(bluetooth_rfkill);
1099register_bluetooth_error:
1100	rfkill_destroy(bluetooth_rfkill);
1101	bluetooth_rfkill = NULL;
1102	if (wifi_rfkill)
1103		rfkill_unregister(wifi_rfkill);
1104register_wifi_error:
1105	rfkill_destroy(wifi_rfkill);
1106	wifi_rfkill = NULL;
1107	return err;
1108}
1109
1110static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
1111{
1112	struct bios_rfkill2_state state;
1113	int err, i;
1114
1115	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
1116				   zero_if_sup(state), sizeof(state));
1117	if (err)
1118		return err < 0 ? err : -EINVAL;
1119
1120	if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
1121		pr_warn("unable to parse 0x1b query output\n");
1122		return -EINVAL;
1123	}
1124
1125	for (i = 0; i < state.count; i++) {
1126		struct rfkill *rfkill;
1127		enum rfkill_type type;
1128		char *name;
1129
1130		switch (state.device[i].radio_type) {
1131		case HPWMI_WIFI:
1132			type = RFKILL_TYPE_WLAN;
1133			name = "hp-wifi";
1134			break;
1135		case HPWMI_BLUETOOTH:
1136			type = RFKILL_TYPE_BLUETOOTH;
1137			name = "hp-bluetooth";
1138			break;
1139		case HPWMI_WWAN:
1140			type = RFKILL_TYPE_WWAN;
1141			name = "hp-wwan";
1142			break;
1143		case HPWMI_GPS:
1144			type = RFKILL_TYPE_GPS;
1145			name = "hp-gps";
1146			break;
1147		default:
1148			pr_warn("unknown device type 0x%x\n",
1149				state.device[i].radio_type);
1150			continue;
1151		}
1152
1153		if (!state.device[i].vendor_id) {
1154			pr_warn("zero device %d while %d reported\n",
1155				i, state.count);
1156			continue;
1157		}
1158
1159		rfkill = rfkill_alloc(name, &device->dev, type,
1160				      &hp_wmi_rfkill2_ops, (void *)(long)i);
1161		if (!rfkill) {
1162			err = -ENOMEM;
1163			goto fail;
1164		}
1165
1166		rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
1167		rfkill2[rfkill2_count].num = i;
1168		rfkill2[rfkill2_count].rfkill = rfkill;
1169
1170		rfkill_init_sw_state(rfkill,
1171				     IS_SWBLOCKED(state.device[i].power));
1172		rfkill_set_hw_state(rfkill,
1173				    IS_HWBLOCKED(state.device[i].power));
1174
1175		if (!(state.device[i].power & HPWMI_POWER_BIOS))
1176			pr_info("device %s blocked by BIOS\n", name);
1177
1178		err = rfkill_register(rfkill);
1179		if (err) {
1180			rfkill_destroy(rfkill);
1181			goto fail;
1182		}
1183
1184		rfkill2_count++;
1185	}
1186
1187	return 0;
1188fail:
1189	for (; rfkill2_count > 0; rfkill2_count--) {
1190		rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
1191		rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
1192	}
1193	return err;
1194}
1195
1196static int platform_profile_omen_get_ec(enum platform_profile_option *profile)
1197{
1198	int tp;
1199
1200	tp = omen_thermal_profile_get();
1201	if (tp < 0)
1202		return tp;
1203
1204	switch (tp) {
1205	case HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE:
1206	case HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE:
1207		*profile = PLATFORM_PROFILE_PERFORMANCE;
1208		break;
1209	case HP_OMEN_V0_THERMAL_PROFILE_DEFAULT:
1210	case HP_OMEN_V1_THERMAL_PROFILE_DEFAULT:
1211		*profile = PLATFORM_PROFILE_BALANCED;
1212		break;
1213	case HP_OMEN_V0_THERMAL_PROFILE_COOL:
1214	case HP_OMEN_V1_THERMAL_PROFILE_COOL:
1215		*profile = PLATFORM_PROFILE_COOL;
1216		break;
1217	default:
1218		return -EINVAL;
1219	}
1220
1221	return 0;
1222}
1223
1224static int platform_profile_omen_get(struct platform_profile_handler *pprof,
1225				     enum platform_profile_option *profile)
1226{
1227	/*
1228	 * We directly return the stored platform profile, as the embedded
1229	 * controller will not accept switching to the performance option when
1230	 * the conditions are not met (e.g. the laptop is not plugged in).
1231	 *
1232	 * If we directly return what the EC reports, the platform profile will
1233	 * immediately "switch back" to normal mode, which is against the
1234	 * expected behaviour from a userspace point of view, as described in
1235	 * the Platform Profile Section page of the kernel documentation.
1236	 *
1237	 * See also omen_powersource_event.
1238	 */
1239	guard(mutex)(&active_platform_profile_lock);
1240	*profile = active_platform_profile;
1241
1242	return 0;
1243}
1244
1245static bool has_omen_thermal_profile_ec_timer(void)
1246{
1247	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
1248
1249	if (!board_name)
1250		return false;
1251
1252	return match_string(omen_timed_thermal_profile_boards,
1253			    ARRAY_SIZE(omen_timed_thermal_profile_boards),
1254			    board_name) >= 0;
1255}
1256
1257inline int omen_thermal_profile_ec_flags_set(enum hp_thermal_profile_omen_flags flags)
1258{
1259	return ec_write(HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET, flags);
1260}
1261
1262inline int omen_thermal_profile_ec_timer_set(u8 value)
1263{
1264	return ec_write(HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET, value);
1265}
1266
1267static int platform_profile_omen_set_ec(enum platform_profile_option profile)
1268{
1269	int err, tp, tp_version;
1270	enum hp_thermal_profile_omen_flags flags = 0;
1271
1272	tp_version = omen_get_thermal_policy_version();
1273
1274	if (tp_version < 0 || tp_version > 1)
1275		return -EOPNOTSUPP;
1276
1277	switch (profile) {
1278	case PLATFORM_PROFILE_PERFORMANCE:
1279		if (tp_version == 0)
1280			tp = HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE;
1281		else
1282			tp = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE;
1283		break;
1284	case PLATFORM_PROFILE_BALANCED:
1285		if (tp_version == 0)
1286			tp = HP_OMEN_V0_THERMAL_PROFILE_DEFAULT;
1287		else
1288			tp = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT;
1289		break;
1290	case PLATFORM_PROFILE_COOL:
1291		if (tp_version == 0)
1292			tp = HP_OMEN_V0_THERMAL_PROFILE_COOL;
1293		else
1294			tp = HP_OMEN_V1_THERMAL_PROFILE_COOL;
1295		break;
1296	default:
1297		return -EOPNOTSUPP;
1298	}
1299
1300	err = omen_thermal_profile_set(tp);
1301	if (err < 0)
1302		return err;
1303
1304	if (has_omen_thermal_profile_ec_timer()) {
1305		err = omen_thermal_profile_ec_timer_set(0);
1306		if (err < 0)
1307			return err;
1308
1309		if (profile == PLATFORM_PROFILE_PERFORMANCE)
1310			flags = HP_OMEN_EC_FLAGS_NOTIMER |
1311				HP_OMEN_EC_FLAGS_TURBO;
1312
1313		err = omen_thermal_profile_ec_flags_set(flags);
1314		if (err < 0)
1315			return err;
1316	}
1317
1318	return 0;
1319}
1320
1321static int platform_profile_omen_set(struct platform_profile_handler *pprof,
1322				     enum platform_profile_option profile)
1323{
1324	int err;
1325
1326	guard(mutex)(&active_platform_profile_lock);
1327
1328	err = platform_profile_omen_set_ec(profile);
1329	if (err < 0)
1330		return err;
1331
1332	active_platform_profile = profile;
1333
1334	return 0;
1335}
1336
1337static int thermal_profile_get(void)
1338{
1339	return hp_wmi_read_int(HPWMI_THERMAL_PROFILE_QUERY);
1340}
1341
1342static int thermal_profile_set(int thermal_profile)
1343{
1344	return hp_wmi_perform_query(HPWMI_THERMAL_PROFILE_QUERY, HPWMI_WRITE, &thermal_profile,
1345							   sizeof(thermal_profile), 0);
1346}
1347
1348static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof,
1349					enum platform_profile_option *profile)
1350{
1351	int tp;
1352
1353	tp = thermal_profile_get();
1354	if (tp < 0)
1355		return tp;
1356
1357	switch (tp) {
1358	case HP_THERMAL_PROFILE_PERFORMANCE:
1359		*profile =  PLATFORM_PROFILE_PERFORMANCE;
1360		break;
1361	case HP_THERMAL_PROFILE_DEFAULT:
1362		*profile =  PLATFORM_PROFILE_BALANCED;
1363		break;
1364	case HP_THERMAL_PROFILE_COOL:
1365		*profile =  PLATFORM_PROFILE_COOL;
1366		break;
1367	case HP_THERMAL_PROFILE_QUIET:
1368		*profile = PLATFORM_PROFILE_QUIET;
1369		break;
1370	default:
1371		return -EINVAL;
1372	}
1373
1374	return 0;
1375}
1376
1377static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof,
1378					enum platform_profile_option profile)
1379{
1380	int err, tp;
1381
1382	switch (profile) {
1383	case PLATFORM_PROFILE_PERFORMANCE:
1384		tp =  HP_THERMAL_PROFILE_PERFORMANCE;
1385		break;
1386	case PLATFORM_PROFILE_BALANCED:
1387		tp =  HP_THERMAL_PROFILE_DEFAULT;
1388		break;
1389	case PLATFORM_PROFILE_COOL:
1390		tp =  HP_THERMAL_PROFILE_COOL;
1391		break;
1392	case PLATFORM_PROFILE_QUIET:
1393		tp = HP_THERMAL_PROFILE_QUIET;
1394		break;
1395	default:
1396		return -EOPNOTSUPP;
1397	}
1398
1399	err = thermal_profile_set(tp);
1400	if (err)
1401		return err;
1402
1403	return 0;
1404}
1405
1406static bool is_victus_thermal_profile(void)
1407{
1408	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
1409
1410	if (!board_name)
1411		return false;
1412
1413	return match_string(victus_thermal_profile_boards,
1414			    ARRAY_SIZE(victus_thermal_profile_boards),
1415			    board_name) >= 0;
1416}
1417
1418static int platform_profile_victus_get_ec(enum platform_profile_option *profile)
1419{
1420	int tp;
1421
1422	tp = omen_thermal_profile_get();
1423	if (tp < 0)
1424		return tp;
1425
1426	switch (tp) {
1427	case HP_VICTUS_THERMAL_PROFILE_PERFORMANCE:
1428		*profile = PLATFORM_PROFILE_PERFORMANCE;
1429		break;
1430	case HP_VICTUS_THERMAL_PROFILE_DEFAULT:
1431		*profile = PLATFORM_PROFILE_BALANCED;
1432		break;
1433	case HP_VICTUS_THERMAL_PROFILE_QUIET:
1434		*profile = PLATFORM_PROFILE_QUIET;
1435		break;
1436	default:
1437		return -EOPNOTSUPP;
1438	}
1439
1440	return 0;
1441}
1442
1443static int platform_profile_victus_get(struct platform_profile_handler *pprof,
1444				       enum platform_profile_option *profile)
1445{
1446	/* Same behaviour as platform_profile_omen_get */
1447	return platform_profile_omen_get(pprof, profile);
1448}
1449
1450static int platform_profile_victus_set_ec(enum platform_profile_option profile)
1451{
1452	int err, tp;
1453
1454	switch (profile) {
1455	case PLATFORM_PROFILE_PERFORMANCE:
1456		tp = HP_VICTUS_THERMAL_PROFILE_PERFORMANCE;
1457		break;
1458	case PLATFORM_PROFILE_BALANCED:
1459		tp = HP_VICTUS_THERMAL_PROFILE_DEFAULT;
1460		break;
1461	case PLATFORM_PROFILE_QUIET:
1462		tp = HP_VICTUS_THERMAL_PROFILE_QUIET;
1463		break;
1464	default:
1465		return -EOPNOTSUPP;
1466	}
1467
1468	err = omen_thermal_profile_set(tp);
1469	if (err < 0)
1470		return err;
1471
1472	return 0;
1473}
1474
1475static int platform_profile_victus_set(struct platform_profile_handler *pprof,
1476				       enum platform_profile_option profile)
1477{
1478	int err;
1479
1480	guard(mutex)(&active_platform_profile_lock);
1481
1482	err = platform_profile_victus_set_ec(profile);
1483	if (err < 0)
1484		return err;
1485
1486	active_platform_profile = profile;
1487
1488	return 0;
1489}
1490
1491static int omen_powersource_event(struct notifier_block *nb,
1492				  unsigned long value,
1493				  void *data)
1494{
1495	struct acpi_bus_event *event_entry = data;
1496	enum platform_profile_option actual_profile;
1497	int err;
1498
1499	if (strcmp(event_entry->device_class, ACPI_AC_CLASS) != 0)
1500		return NOTIFY_DONE;
1501
1502	pr_debug("Received power source device event\n");
1503
1504	guard(mutex)(&active_platform_profile_lock);
1505
1506	/*
1507	 * This handler can only be called on Omen and Victus models, so
1508	 * there's no need to call is_victus_thermal_profile() here.
1509	 */
1510	if (is_omen_thermal_profile())
1511		err = platform_profile_omen_get_ec(&actual_profile);
1512	else
1513		err = platform_profile_victus_get_ec(&actual_profile);
1514
1515	if (err < 0) {
1516		/*
1517		 * Although we failed to get the current platform profile, we
1518		 * still want the other event consumers to process it.
1519		 */
1520		pr_warn("Failed to read current platform profile (%d)\n", err);
1521		return NOTIFY_DONE;
1522	}
1523
1524	/*
1525	 * If we're back on AC and that the user-chosen power profile is
1526	 * different from what the EC reports, we restore the user-chosen
1527	 * one.
1528	 */
1529	if (power_supply_is_system_supplied() <= 0 ||
1530	    active_platform_profile == actual_profile) {
1531		pr_debug("Platform profile update skipped, conditions unmet\n");
1532		return NOTIFY_DONE;
1533	}
1534
1535	if (is_omen_thermal_profile())
1536		err = platform_profile_omen_set_ec(active_platform_profile);
1537	else
1538		err = platform_profile_victus_set_ec(active_platform_profile);
1539
1540	if (err < 0) {
1541		pr_warn("Failed to restore platform profile (%d)\n", err);
1542		return NOTIFY_DONE;
1543	}
1544
1545	return NOTIFY_OK;
1546}
1547
1548static int omen_register_powersource_event_handler(void)
1549{
1550	int err;
1551
1552	platform_power_source_nb.notifier_call = omen_powersource_event;
1553	err = register_acpi_notifier(&platform_power_source_nb);
1554
1555	if (err < 0) {
1556		pr_warn("Failed to install ACPI power source notify handler\n");
1557		return err;
1558	}
1559
1560	return 0;
1561}
1562
1563static inline void omen_unregister_powersource_event_handler(void)
1564{
1565	unregister_acpi_notifier(&platform_power_source_nb);
1566}
1567
1568static int thermal_profile_setup(void)
1569{
1570	int err, tp;
1571
1572	if (is_omen_thermal_profile()) {
1573		err = platform_profile_omen_get_ec(&active_platform_profile);
1574		if (err < 0)
1575			return err;
1576
1577		/*
1578		 * call thermal profile write command to ensure that the
1579		 * firmware correctly sets the OEM variables
1580		 */
1581		err = platform_profile_omen_set_ec(active_platform_profile);
1582		if (err < 0)
1583			return err;
1584
1585		platform_profile_handler.profile_get = platform_profile_omen_get;
1586		platform_profile_handler.profile_set = platform_profile_omen_set;
1587
1588		set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
1589	} else if (is_victus_thermal_profile()) {
1590		err = platform_profile_victus_get_ec(&active_platform_profile);
1591		if (err < 0)
1592			return err;
1593
1594		/*
1595		 * call thermal profile write command to ensure that the
1596		 * firmware correctly sets the OEM variables
1597		 */
1598		err = platform_profile_victus_set_ec(active_platform_profile);
1599		if (err < 0)
1600			return err;
1601
1602		platform_profile_handler.profile_get = platform_profile_victus_get;
1603		platform_profile_handler.profile_set = platform_profile_victus_set;
1604
1605		set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
1606	} else {
1607		tp = thermal_profile_get();
1608
1609		if (tp < 0)
1610			return tp;
1611
1612		/*
1613		 * call thermal profile write command to ensure that the
1614		 * firmware correctly sets the OEM variables for the DPTF
1615		 */
1616		err = thermal_profile_set(tp);
1617		if (err)
1618			return err;
1619
1620		platform_profile_handler.profile_get = hp_wmi_platform_profile_get;
1621		platform_profile_handler.profile_set = hp_wmi_platform_profile_set;
1622
1623		set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
1624		set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
1625	}
1626
1627	set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
1628	set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
1629
1630	err = platform_profile_register(&platform_profile_handler);
1631	if (err)
1632		return err;
1633
1634	platform_profile_support = true;
1635
1636	return 0;
1637}
1638
1639static int hp_wmi_hwmon_init(void);
1640
1641static int __init hp_wmi_bios_setup(struct platform_device *device)
1642{
1643	int err;
1644	/* clear detected rfkill devices */
1645	wifi_rfkill = NULL;
1646	bluetooth_rfkill = NULL;
1647	wwan_rfkill = NULL;
1648	rfkill2_count = 0;
1649
1650	/*
1651	 * In pre-2009 BIOS, command 1Bh return 0x4 to indicate that
1652	 * BIOS no longer controls the power for the wireless
1653	 * devices. All features supported by this command will no
1654	 * longer be supported.
1655	 */
1656	if (!hp_wmi_bios_2009_later()) {
1657		if (hp_wmi_rfkill_setup(device))
1658			hp_wmi_rfkill2_setup(device);
1659	}
1660
1661	err = hp_wmi_hwmon_init();
1662
1663	if (err < 0)
1664		return err;
1665
1666	thermal_profile_setup();
1667
1668	return 0;
1669}
1670
1671static void __exit hp_wmi_bios_remove(struct platform_device *device)
1672{
1673	int i;
1674
1675	for (i = 0; i < rfkill2_count; i++) {
1676		rfkill_unregister(rfkill2[i].rfkill);
1677		rfkill_destroy(rfkill2[i].rfkill);
1678	}
1679
1680	if (wifi_rfkill) {
1681		rfkill_unregister(wifi_rfkill);
1682		rfkill_destroy(wifi_rfkill);
1683	}
1684	if (bluetooth_rfkill) {
1685		rfkill_unregister(bluetooth_rfkill);
1686		rfkill_destroy(bluetooth_rfkill);
1687	}
1688	if (wwan_rfkill) {
1689		rfkill_unregister(wwan_rfkill);
1690		rfkill_destroy(wwan_rfkill);
1691	}
1692
1693	if (platform_profile_support)
1694		platform_profile_remove();
1695}
1696
1697static int hp_wmi_resume_handler(struct device *device)
1698{
1699	/*
1700	 * Hardware state may have changed while suspended, so trigger
1701	 * input events for the current state. As this is a switch,
1702	 * the input layer will only actually pass it on if the state
1703	 * changed.
1704	 */
1705	if (hp_wmi_input_dev) {
1706		if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
1707			input_report_switch(hp_wmi_input_dev, SW_DOCK,
1708					    hp_wmi_get_dock_state());
1709		if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
1710			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
1711					    hp_wmi_get_tablet_mode());
1712		input_sync(hp_wmi_input_dev);
1713	}
1714
1715	if (rfkill2_count)
1716		hp_wmi_rfkill2_refresh();
1717
1718	if (wifi_rfkill)
1719		rfkill_set_states(wifi_rfkill,
1720				  hp_wmi_get_sw_state(HPWMI_WIFI),
1721				  hp_wmi_get_hw_state(HPWMI_WIFI));
1722	if (bluetooth_rfkill)
1723		rfkill_set_states(bluetooth_rfkill,
1724				  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
1725				  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
1726	if (wwan_rfkill)
1727		rfkill_set_states(wwan_rfkill,
1728				  hp_wmi_get_sw_state(HPWMI_WWAN),
1729				  hp_wmi_get_hw_state(HPWMI_WWAN));
1730
1731	return 0;
1732}
1733
1734static const struct dev_pm_ops hp_wmi_pm_ops = {
1735	.resume  = hp_wmi_resume_handler,
1736	.restore  = hp_wmi_resume_handler,
1737};
1738
1739/*
1740 * hp_wmi_bios_remove() lives in .exit.text. For drivers registered via
1741 * module_platform_driver_probe() this is ok because they cannot get unbound at
1742 * runtime. So mark the driver struct with __refdata to prevent modpost
1743 * triggering a section mismatch warning.
1744 */
1745static struct platform_driver hp_wmi_driver __refdata = {
1746	.driver = {
1747		.name = "hp-wmi",
1748		.pm = &hp_wmi_pm_ops,
1749		.dev_groups = hp_wmi_groups,
1750	},
1751	.remove = __exit_p(hp_wmi_bios_remove),
1752};
1753
1754static umode_t hp_wmi_hwmon_is_visible(const void *data,
1755				       enum hwmon_sensor_types type,
1756				       u32 attr, int channel)
1757{
1758	switch (type) {
1759	case hwmon_pwm:
1760		return 0644;
1761	case hwmon_fan:
1762		if (hp_wmi_get_fan_speed(channel) >= 0)
1763			return 0444;
1764		break;
1765	default:
1766		return 0;
1767	}
1768
1769	return 0;
1770}
1771
1772static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
1773			     u32 attr, int channel, long *val)
1774{
1775	int ret;
1776
1777	switch (type) {
1778	case hwmon_fan:
1779		ret = hp_wmi_get_fan_speed(channel);
1780
1781		if (ret < 0)
1782			return ret;
1783		*val = ret;
1784		return 0;
1785	case hwmon_pwm:
1786		switch (hp_wmi_fan_speed_max_get()) {
1787		case 0:
1788			/* 0 is automatic fan, which is 2 for hwmon */
1789			*val = 2;
1790			return 0;
1791		case 1:
1792			/* 1 is max fan, which is 0
1793			 * (no fan speed control) for hwmon
1794			 */
1795			*val = 0;
1796			return 0;
1797		default:
1798			/* shouldn't happen */
1799			return -ENODATA;
1800		}
1801	default:
1802		return -EINVAL;
1803	}
1804}
1805
1806static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
1807			      u32 attr, int channel, long val)
1808{
1809	switch (type) {
1810	case hwmon_pwm:
1811		switch (val) {
1812		case 0:
1813			/* 0 is no fan speed control (max), which is 1 for us */
1814			return hp_wmi_fan_speed_max_set(1);
1815		case 2:
1816			/* 2 is automatic speed control, which is 0 for us */
1817			return hp_wmi_fan_speed_max_set(0);
1818		default:
1819			/* we don't support manual fan speed control */
1820			return -EINVAL;
1821		}
1822	default:
1823		return -EOPNOTSUPP;
1824	}
1825}
1826
1827static const struct hwmon_channel_info * const info[] = {
1828	HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT),
1829	HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE),
1830	NULL
1831};
1832
1833static const struct hwmon_ops ops = {
1834	.is_visible = hp_wmi_hwmon_is_visible,
1835	.read = hp_wmi_hwmon_read,
1836	.write = hp_wmi_hwmon_write,
1837};
1838
1839static const struct hwmon_chip_info chip_info = {
1840	.ops = &ops,
1841	.info = info,
1842};
1843
1844static int hp_wmi_hwmon_init(void)
1845{
1846	struct device *dev = &hp_wmi_platform_dev->dev;
1847	struct device *hwmon;
1848
1849	hwmon = devm_hwmon_device_register_with_info(dev, "hp", &hp_wmi_driver,
1850						     &chip_info, NULL);
1851
1852	if (IS_ERR(hwmon)) {
1853		dev_err(dev, "Could not register hp hwmon device\n");
1854		return PTR_ERR(hwmon);
1855	}
1856
1857	return 0;
1858}
1859
1860static int __init hp_wmi_init(void)
1861{
1862	int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
1863	int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
1864	int err, tmp = 0;
1865
1866	if (!bios_capable && !event_capable)
1867		return -ENODEV;
1868
1869	if (hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, HPWMI_READ, &tmp,
1870				 sizeof(tmp), sizeof(tmp)) == HPWMI_RET_INVALID_PARAMETERS)
1871		zero_insize_support = true;
1872
1873	if (event_capable) {
1874		err = hp_wmi_input_setup();
1875		if (err)
1876			return err;
1877	}
1878
1879	if (bios_capable) {
1880		hp_wmi_platform_dev =
1881			platform_device_register_simple("hp-wmi", PLATFORM_DEVID_NONE, NULL, 0);
1882		if (IS_ERR(hp_wmi_platform_dev)) {
1883			err = PTR_ERR(hp_wmi_platform_dev);
1884			goto err_destroy_input;
1885		}
1886
1887		err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup);
1888		if (err)
1889			goto err_unregister_device;
1890	}
1891
1892	if (is_omen_thermal_profile() || is_victus_thermal_profile()) {
1893		err = omen_register_powersource_event_handler();
1894		if (err)
1895			goto err_unregister_device;
1896	}
1897
1898	return 0;
1899
1900err_unregister_device:
1901	platform_device_unregister(hp_wmi_platform_dev);
1902err_destroy_input:
1903	if (event_capable)
1904		hp_wmi_input_destroy();
1905
1906	return err;
1907}
1908module_init(hp_wmi_init);
1909
1910static void __exit hp_wmi_exit(void)
1911{
1912	if (is_omen_thermal_profile() || is_victus_thermal_profile())
1913		omen_unregister_powersource_event_handler();
1914
1915	if (wmi_has_guid(HPWMI_EVENT_GUID))
1916		hp_wmi_input_destroy();
1917
1918	if (camera_shutter_input_dev)
1919		input_unregister_device(camera_shutter_input_dev);
1920
1921	if (hp_wmi_platform_dev) {
1922		platform_device_unregister(hp_wmi_platform_dev);
1923		platform_driver_unregister(&hp_wmi_driver);
1924	}
1925}
1926module_exit(hp_wmi_exit);