File Index
Files and directories
Sign in
FILE

hp-wmi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/x86/hp/hp-wmi.c C
   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 HP_FAN_SPEED_AUTOMATIC	 0x00
  49#define HP_POWER_LIMIT_DEFAULT	 0x00
  50#define HP_POWER_LIMIT_NO_CHANGE 0xFF
  51
  52#define ACPI_AC_CLASS "ac_adapter"
  53
  54#define zero_if_sup(tmp) (zero_insize_support?0:sizeof(tmp)) // use when zero insize is required
  55
  56enum hp_thermal_profile_omen_v0 {
  57	HP_OMEN_V0_THERMAL_PROFILE_DEFAULT		= 0x00,
  58	HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE		= 0x01,
  59	HP_OMEN_V0_THERMAL_PROFILE_COOL			= 0x02,
  60};
  61
  62enum hp_thermal_profile_omen_v1 {
  63	HP_OMEN_V1_THERMAL_PROFILE_DEFAULT		= 0x30,
  64	HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE		= 0x31,
  65	HP_OMEN_V1_THERMAL_PROFILE_COOL			= 0x50,
  66};
  67
  68enum hp_thermal_profile_omen_flags {
  69	HP_OMEN_EC_FLAGS_TURBO				= 0x04,
  70	HP_OMEN_EC_FLAGS_NOTIMER			= 0x02,
  71	HP_OMEN_EC_FLAGS_JUSTSET			= 0x01,
  72};
  73
  74enum hp_thermal_profile_victus {
  75	HP_VICTUS_THERMAL_PROFILE_DEFAULT		= 0x00,
  76	HP_VICTUS_THERMAL_PROFILE_PERFORMANCE		= 0x01,
  77	HP_VICTUS_THERMAL_PROFILE_QUIET			= 0x03,
  78};
  79
  80enum hp_thermal_profile_victus_s {
  81	HP_VICTUS_S_THERMAL_PROFILE_DEFAULT		= 0x00,
  82	HP_VICTUS_S_THERMAL_PROFILE_PERFORMANCE		= 0x01,
  83};
  84
  85enum hp_thermal_profile {
  86	HP_THERMAL_PROFILE_PERFORMANCE			= 0x00,
  87	HP_THERMAL_PROFILE_DEFAULT			= 0x01,
  88	HP_THERMAL_PROFILE_COOL				= 0x02,
  89	HP_THERMAL_PROFILE_QUIET			= 0x03,
  90};
  91
  92struct thermal_profile_params {
  93	u8 performance;
  94	u8 balanced;
  95	u8 low_power;
  96};
  97
  98static const struct thermal_profile_params victus_s_thermal_params = {
  99	.performance	= HP_VICTUS_S_THERMAL_PROFILE_PERFORMANCE,
 100	.balanced	= HP_VICTUS_S_THERMAL_PROFILE_DEFAULT,
 101	.low_power	= HP_VICTUS_S_THERMAL_PROFILE_DEFAULT,
 102};
 103
 104static const struct thermal_profile_params omen_v1_thermal_params = {
 105	.performance	= HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE,
 106	.balanced	= HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
 107	.low_power	= HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
 108};
 109
 110/*
 111 * A generic pointer for the currently-active board's thermal profile
 112 * parameters.
 113 */
 114static struct thermal_profile_params *active_thermal_profile_params;
 115
 116/* DMI board names of devices that should use the omen specific path for
 117 * thermal profiles.
 118 * This was obtained by taking a look in the windows omen command center
 119 * app and parsing a json file that they use to figure out what capabilities
 120 * the device should have.
 121 * A device is considered an omen if the DisplayName in that list contains
 122 * "OMEN", and it can use the thermal profile stuff if the "Feature" array
 123 * contains "PerformanceControl".
 124 */
 125static const char * const omen_thermal_profile_boards[] = {
 126	"84DA", "84DB", "84DC",
 127	"8572", "8573", "8574", "8575",
 128	"8600", "8601", "8602", "8603", "8604", "8605", "8606", "8607", "860A",
 129	"8746", "8747", "8748", "8749", "874A", "8786", "8787", "8788", "878A",
 130	"878B", "878C", "87B5",
 131	"886B", "886C", "88C8", "88CB", "88D1", "88D2", "88F4", "88F5", "88F6",
 132	"88F7", "88FD", "88FE", "88FF",
 133	"8900", "8901", "8902", "8912", "8917", "8918", "8949", "894A", "89EB",
 134	"8A15", "8A42",
 135	"8BAD",
 136	"8E41",
 137};
 138
 139/* DMI Board names of Omen laptops that are specifically set to be thermal
 140 * profile version 0 by the Omen Command Center app, regardless of what
 141 * the get system design information WMI call returns
 142 */
 143static const char * const omen_thermal_profile_force_v0_boards[] = {
 144	"8607",
 145	"8746", "8747", "8748", "8749", "874A",
 146};
 147
 148/* DMI board names of Omen laptops that have a thermal profile timer which will
 149 * cause the embedded controller to set the thermal profile back to
 150 * "balanced" when reaching zero.
 151 */
 152static const char * const omen_timed_thermal_profile_boards[] = {
 153	"8A15", "8A42",
 154	"8BAD",
 155};
 156
 157/* DMI Board names of Victus 16-d laptops */
 158static const char * const victus_thermal_profile_boards[] = {
 159	"88F8",
 160	"8A25",
 161};
 162
 163/* DMI Board names of Victus 16-r and Victus 16-s laptops */
 164static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = {
 165	{
 166		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BAB") },
 167		.driver_data = (void *)&omen_v1_thermal_params,
 168	},
 169	{
 170		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") },
 171		.driver_data = (void *)&victus_s_thermal_params,
 172	},
 173	{
 174		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCD") },
 175		.driver_data = (void *)&omen_v1_thermal_params,
 176	},
 177	{
 178		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD4") },
 179		.driver_data = (void *)&victus_s_thermal_params,
 180	},
 181	{
 182		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD5") },
 183		.driver_data = (void *)&victus_s_thermal_params,
 184	},
 185	{
 186		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8C76") },
 187		.driver_data = (void *)&omen_v1_thermal_params,
 188	},
 189	{
 190		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") },
 191		.driver_data = (void *)&omen_v1_thermal_params,
 192	},
 193	{
 194		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8C99") },
 195		.driver_data = (void *)&victus_s_thermal_params,
 196	},
 197	{
 198		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8C9C") },
 199		.driver_data = (void *)&victus_s_thermal_params,
 200	},
 201	{
 202		.matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") },
 203		.driver_data = (void *)&victus_s_thermal_params,
 204	},
 205	{},
 206};
 207
 208static bool is_victus_s_board;
 209
 210enum hp_wmi_radio {
 211	HPWMI_WIFI	= 0x0,
 212	HPWMI_BLUETOOTH	= 0x1,
 213	HPWMI_WWAN	= 0x2,
 214	HPWMI_GPS	= 0x3,
 215};
 216
 217enum hp_wmi_event_ids {
 218	HPWMI_DOCK_EVENT		= 0x01,
 219	HPWMI_PARK_HDD			= 0x02,
 220	HPWMI_SMART_ADAPTER		= 0x03,
 221	HPWMI_BEZEL_BUTTON		= 0x04,
 222	HPWMI_WIRELESS			= 0x05,
 223	HPWMI_CPU_BATTERY_THROTTLE	= 0x06,
 224	HPWMI_LOCK_SWITCH		= 0x07,
 225	HPWMI_LID_SWITCH		= 0x08,
 226	HPWMI_SCREEN_ROTATION		= 0x09,
 227	HPWMI_COOLSENSE_SYSTEM_MOBILE	= 0x0A,
 228	HPWMI_COOLSENSE_SYSTEM_HOT	= 0x0B,
 229	HPWMI_PROXIMITY_SENSOR		= 0x0C,
 230	HPWMI_BACKLIT_KB_BRIGHTNESS	= 0x0D,
 231	HPWMI_PEAKSHIFT_PERIOD		= 0x0F,
 232	HPWMI_BATTERY_CHARGE_PERIOD	= 0x10,
 233	HPWMI_SANITIZATION_MODE		= 0x17,
 234	HPWMI_CAMERA_TOGGLE		= 0x1A,
 235	HPWMI_FN_P_HOTKEY		= 0x1B,
 236	HPWMI_OMEN_KEY			= 0x1D,
 237	HPWMI_SMART_EXPERIENCE_APP	= 0x21,
 238};
 239
 240/*
 241 * struct bios_args buffer is dynamically allocated.  New WMI command types
 242 * were introduced that exceeds 128-byte data size.  Changes to handle
 243 * the data size allocation scheme were kept in hp_wmi_perform_qurey function.
 244 */
 245struct bios_args {
 246	u32 signature;
 247	u32 command;
 248	u32 commandtype;
 249	u32 datasize;
 250	u8 data[];
 251};
 252
 253enum hp_wmi_commandtype {
 254	HPWMI_DISPLAY_QUERY		= 0x01,
 255	HPWMI_HDDTEMP_QUERY		= 0x02,
 256	HPWMI_ALS_QUERY			= 0x03,
 257	HPWMI_HARDWARE_QUERY		= 0x04,
 258	HPWMI_WIRELESS_QUERY		= 0x05,
 259	HPWMI_BATTERY_QUERY		= 0x07,
 260	HPWMI_BIOS_QUERY		= 0x09,
 261	HPWMI_FEATURE_QUERY		= 0x0b,
 262	HPWMI_HOTKEY_QUERY		= 0x0c,
 263	HPWMI_FEATURE2_QUERY		= 0x0d,
 264	HPWMI_WIRELESS2_QUERY		= 0x1b,
 265	HPWMI_POSTCODEERROR_QUERY	= 0x2a,
 266	HPWMI_SYSTEM_DEVICE_MODE	= 0x40,
 267	HPWMI_THERMAL_PROFILE_QUERY	= 0x4c,
 268};
 269
 270struct victus_power_limits {
 271	u8 pl1;
 272	u8 pl2;
 273	u8 pl4;
 274	u8 cpu_gpu_concurrent_limit;
 275};
 276
 277struct victus_gpu_power_modes {
 278	u8 ctgp_enable;
 279	u8 ppab_enable;
 280	u8 dstate;
 281	u8 gpu_slowdown_temp;
 282};
 283
 284enum hp_wmi_gm_commandtype {
 285	HPWMI_FAN_SPEED_GET_QUERY		= 0x11,
 286	HPWMI_SET_PERFORMANCE_MODE		= 0x1A,
 287	HPWMI_FAN_SPEED_MAX_GET_QUERY		= 0x26,
 288	HPWMI_FAN_SPEED_MAX_SET_QUERY		= 0x27,
 289	HPWMI_GET_SYSTEM_DESIGN_DATA		= 0x28,
 290	HPWMI_FAN_COUNT_GET_QUERY		= 0x10,
 291	HPWMI_GET_GPU_THERMAL_MODES_QUERY	= 0x21,
 292	HPWMI_SET_GPU_THERMAL_MODES_QUERY	= 0x22,
 293	HPWMI_SET_POWER_LIMITS_QUERY		= 0x29,
 294	HPWMI_VICTUS_S_FAN_SPEED_GET_QUERY	= 0x2D,
 295	HPWMI_FAN_SPEED_SET_QUERY		= 0x2E,
 296};
 297
 298enum hp_wmi_command {
 299	HPWMI_READ	= 0x01,
 300	HPWMI_WRITE	= 0x02,
 301	HPWMI_ODM	= 0x03,
 302	HPWMI_GM	= 0x20008,
 303};
 304
 305enum hp_wmi_hardware_mask {
 306	HPWMI_DOCK_MASK		= 0x01,
 307	HPWMI_TABLET_MASK	= 0x04,
 308};
 309
 310struct bios_return {
 311	u32 sigpass;
 312	u32 return_code;
 313};
 314
 315enum hp_return_value {
 316	HPWMI_RET_WRONG_SIGNATURE	= 0x02,
 317	HPWMI_RET_UNKNOWN_COMMAND	= 0x03,
 318	HPWMI_RET_UNKNOWN_CMDTYPE	= 0x04,
 319	HPWMI_RET_INVALID_PARAMETERS	= 0x05,
 320};
 321
 322enum hp_wireless2_bits {
 323	HPWMI_POWER_STATE	= 0x01,
 324	HPWMI_POWER_SOFT	= 0x02,
 325	HPWMI_POWER_BIOS	= 0x04,
 326	HPWMI_POWER_HARD	= 0x08,
 327	HPWMI_POWER_FW_OR_HW	= HPWMI_POWER_BIOS | HPWMI_POWER_HARD,
 328};
 329
 330#define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW)
 331#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
 332
 333struct bios_rfkill2_device_state {
 334	u8 radio_type;
 335	u8 bus_type;
 336	u16 vendor_id;
 337	u16 product_id;
 338	u16 subsys_vendor_id;
 339	u16 subsys_product_id;
 340	u8 rfkill_id;
 341	u8 power;
 342	u8 unknown[4];
 343};
 344
 345/* 7 devices fit into the 128 byte buffer */
 346#define HPWMI_MAX_RFKILL2_DEVICES	7
 347
 348struct bios_rfkill2_state {
 349	u8 unknown[7];
 350	u8 count;
 351	u8 pad[8];
 352	struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
 353};
 354
 355static const struct key_entry hp_wmi_keymap[] = {
 356	{ KE_KEY, 0x02,    { KEY_BRIGHTNESSUP } },
 357	{ KE_KEY, 0x03,    { KEY_BRIGHTNESSDOWN } },
 358	{ KE_KEY, 0x270,   { KEY_MICMUTE } },
 359	{ KE_KEY, 0x20e6,  { KEY_PROG1 } },
 360	{ KE_KEY, 0x20e8,  { KEY_MEDIA } },
 361	{ KE_KEY, 0x2142,  { KEY_MEDIA } },
 362	{ KE_KEY, 0x213b,  { KEY_INFO } },
 363	{ KE_KEY, 0x2169,  { KEY_ROTATE_DISPLAY } },
 364	{ KE_KEY, 0x216a,  { KEY_SETUP } },
 365	{ KE_IGNORE, 0x21a4,  }, /* Win Lock On */
 366	{ KE_IGNORE, 0x121a4, }, /* Win Lock Off */
 367	{ KE_KEY, 0x21a5,  { KEY_PROG2 } }, /* HP Omen Key */
 368	{ KE_KEY, 0x21a7,  { KEY_FN_ESC } },
 369	{ KE_KEY, 0x21a8,  { KEY_PROG2 } }, /* HP Envy x360 programmable key */
 370	{ KE_KEY, 0x21a9,  { KEY_TOUCHPAD_OFF } },
 371	{ KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } },
 372	{ KE_KEY, 0x231b,  { KEY_HELP } },
 373	{ KE_END, 0 }
 374};
 375
 376/*
 377 * Mutex for the active_platform_profile variable,
 378 * see omen_powersource_event.
 379 */
 380static DEFINE_MUTEX(active_platform_profile_lock);
 381
 382static struct input_dev *hp_wmi_input_dev;
 383static struct input_dev *camera_shutter_input_dev;
 384static struct platform_device *hp_wmi_platform_dev;
 385static struct device *platform_profile_device;
 386static struct notifier_block platform_power_source_nb;
 387static enum platform_profile_option active_platform_profile;
 388static bool platform_profile_support;
 389static bool zero_insize_support;
 390
 391static struct rfkill *wifi_rfkill;
 392static struct rfkill *bluetooth_rfkill;
 393static struct rfkill *wwan_rfkill;
 394
 395struct rfkill2_device {
 396	u8 id;
 397	int num;
 398	struct rfkill *rfkill;
 399};
 400
 401static int rfkill2_count;
 402static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
 403
 404/*
 405 * Chassis Types values were obtained from SMBIOS reference
 406 * specification version 3.00. A complete list of system enclosures
 407 * and chassis types is available on Table 17.
 408 */
 409static const char * const tablet_chassis_types[] = {
 410	"30", /* Tablet*/
 411	"31", /* Convertible */
 412	"32"  /* Detachable */
 413};
 414
 415#define DEVICE_MODE_TABLET	0x06
 416
 417/* map output size to the corresponding WMI method id */
 418static inline int encode_outsize_for_pvsz(int outsize)
 419{
 420	if (outsize > 4096)
 421		return -EINVAL;
 422	if (outsize > 1024)
 423		return 5;
 424	if (outsize > 128)
 425		return 4;
 426	if (outsize > 4)
 427		return 3;
 428	if (outsize > 0)
 429		return 2;
 430	return 1;
 431}
 432
 433/*
 434 * hp_wmi_perform_query
 435 *
 436 * query:	The commandtype (enum hp_wmi_commandtype)
 437 * write:	The command (enum hp_wmi_command)
 438 * buffer:	Buffer used as input and/or output
 439 * insize:	Size of input buffer
 440 * outsize:	Size of output buffer
 441 *
 442 * returns zero on success
 443 *         an HP WMI query specific error code (which is positive)
 444 *         -EINVAL if the query was not successful at all
 445 *         -EINVAL if the output buffer size exceeds buffersize
 446 *
 447 * Note: The buffersize must at least be the maximum of the input and output
 448 *       size. E.g. Battery info query is defined to have 1 byte input
 449 *       and 128 byte output. The caller would do:
 450 *       buffer = kzalloc(128, GFP_KERNEL);
 451 *       ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128)
 452 */
 453static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
 454				void *buffer, int insize, int outsize)
 455{
 456	struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL };
 457	struct bios_return *bios_return;
 458	union acpi_object *obj = NULL;
 459	struct bios_args *args = NULL;
 460	int mid, actual_insize, actual_outsize;
 461	size_t bios_args_size;
 462	int ret;
 463
 464	mid = encode_outsize_for_pvsz(outsize);
 465	if (WARN_ON(mid < 0))
 466		return mid;
 467
 468	actual_insize = max(insize, 128);
 469	bios_args_size = struct_size(args, data, actual_insize);
 470	args = kmalloc(bios_args_size, GFP_KERNEL);
 471	if (!args)
 472		return -ENOMEM;
 473
 474	input.length = bios_args_size;
 475	input.pointer = args;
 476
 477	args->signature = 0x55434553;
 478	args->command = command;
 479	args->commandtype = query;
 480	args->datasize = insize;
 481	memcpy(args->data, buffer, flex_array_size(args, data, insize));
 482
 483	ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
 484	if (ret)
 485		goto out_free;
 486
 487	obj = output.pointer;
 488	if (!obj) {
 489		ret = -EINVAL;
 490		goto out_free;
 491	}
 492
 493	if (obj->type != ACPI_TYPE_BUFFER) {
 494		pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret);
 495		ret = -EINVAL;
 496		goto out_free;
 497	}
 498
 499	bios_return = (struct bios_return *)obj->buffer.pointer;
 500	ret = bios_return->return_code;
 501
 502	if (ret) {
 503		if (ret != HPWMI_RET_UNKNOWN_COMMAND &&
 504		    ret != HPWMI_RET_UNKNOWN_CMDTYPE)
 505			pr_warn("query 0x%x returned error 0x%x\n", query, ret);
 506		goto out_free;
 507	}
 508
 509	/* Ignore output data of zero size */
 510	if (!outsize)
 511		goto out_free;
 512
 513	actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
 514	memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
 515	memset(buffer + actual_outsize, 0, outsize - actual_outsize);
 516
 517out_free:
 518	kfree(obj);
 519	kfree(args);
 520	return ret;
 521}
 522
 523/*
 524 * Calling this hp_wmi_get_fan_count_userdefine_trigger function also enables
 525 * and/or maintains the laptop in user defined thermal and fan states, instead
 526 * of using a fallback state. After a 120 seconds timeout however, the laptop
 527 * goes back to its fallback state.
 528 */
 529static int hp_wmi_get_fan_count_userdefine_trigger(void)
 530{
 531	u8 fan_data[4] = {};
 532	int ret;
 533
 534	ret = hp_wmi_perform_query(HPWMI_FAN_COUNT_GET_QUERY, HPWMI_GM,
 535				   &fan_data, sizeof(u8),
 536				   sizeof(fan_data));
 537	if (ret != 0)
 538		return -EINVAL;
 539
 540	return fan_data[0]; /* Others bytes aren't providing fan count */
 541}
 542
 543static int hp_wmi_get_fan_speed(int fan)
 544{
 545	u8 fsh, fsl;
 546	char fan_data[4] = { fan, 0, 0, 0 };
 547
 548	int ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_GET_QUERY, HPWMI_GM,
 549				       &fan_data, sizeof(char),
 550				       sizeof(fan_data));
 551
 552	if (ret != 0)
 553		return -EINVAL;
 554
 555	fsh = fan_data[2];
 556	fsl = fan_data[3];
 557
 558	return (fsh << 8) | fsl;
 559}
 560
 561static int hp_wmi_get_fan_speed_victus_s(int fan)
 562{
 563	u8 fan_data[128] = {};
 564	int ret;
 565
 566	if (fan < 0 || fan >= sizeof(fan_data))
 567		return -EINVAL;
 568
 569	ret = hp_wmi_perform_query(HPWMI_VICTUS_S_FAN_SPEED_GET_QUERY,
 570				   HPWMI_GM, &fan_data, sizeof(u8),
 571				   sizeof(fan_data));
 572	if (ret != 0)
 573		return -EINVAL;
 574
 575	return fan_data[fan] * 100;
 576}
 577
 578static int hp_wmi_read_int(int query)
 579{
 580	int val = 0, ret;
 581
 582	ret = hp_wmi_perform_query(query, HPWMI_READ, &val,
 583				   zero_if_sup(val), sizeof(val));
 584
 585	if (ret)
 586		return ret < 0 ? ret : -EINVAL;
 587
 588	return val;
 589}
 590
 591static int hp_wmi_get_dock_state(void)
 592{
 593	int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY);
 594
 595	if (state < 0)
 596		return state;
 597
 598	return !!(state & HPWMI_DOCK_MASK);
 599}
 600
 601static int hp_wmi_get_tablet_mode(void)
 602{
 603	char system_device_mode[4] = { 0 };
 604	const char *chassis_type;
 605	bool tablet_found;
 606	int ret;
 607
 608	chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
 609	if (!chassis_type)
 610		return -ENODEV;
 611
 612	tablet_found = match_string(tablet_chassis_types,
 613				    ARRAY_SIZE(tablet_chassis_types),
 614				    chassis_type) >= 0;
 615	if (!tablet_found)
 616		return -ENODEV;
 617
 618	ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ,
 619				   system_device_mode, zero_if_sup(system_device_mode),
 620				   sizeof(system_device_mode));
 621	if (ret < 0)
 622		return ret;
 623
 624	return system_device_mode[0] == DEVICE_MODE_TABLET;
 625}
 626
 627static int omen_thermal_profile_set(int mode)
 628{
 629	/* The Omen Control Center actively sets the first byte of the buffer to
 630	 * 255, so let's mimic this behaviour to be as close as possible to
 631	 * the original software.
 632	 */
 633	char buffer[2] = {-1, mode};
 634	int ret;
 635
 636	ret = hp_wmi_perform_query(HPWMI_SET_PERFORMANCE_MODE, HPWMI_GM,
 637				   &buffer, sizeof(buffer), 0);
 638
 639	if (ret)
 640		return ret < 0 ? ret : -EINVAL;
 641
 642	return mode;
 643}
 644
 645static bool is_omen_thermal_profile(void)
 646{
 647	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
 648
 649	if (!board_name)
 650		return false;
 651
 652	return match_string(omen_thermal_profile_boards,
 653			    ARRAY_SIZE(omen_thermal_profile_boards),
 654			    board_name) >= 0;
 655}
 656
 657static int omen_get_thermal_policy_version(void)
 658{
 659	unsigned char buffer[8] = { 0 };
 660	int ret;
 661
 662	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
 663
 664	if (board_name) {
 665		int matches = match_string(omen_thermal_profile_force_v0_boards,
 666			ARRAY_SIZE(omen_thermal_profile_force_v0_boards),
 667			board_name);
 668		if (matches >= 0)
 669			return 0;
 670	}
 671
 672	ret = hp_wmi_perform_query(HPWMI_GET_SYSTEM_DESIGN_DATA, HPWMI_GM,
 673				   &buffer, sizeof(buffer), sizeof(buffer));
 674
 675	if (ret)
 676		return ret < 0 ? ret : -EINVAL;
 677
 678	return buffer[3];
 679}
 680
 681static int omen_thermal_profile_get(void)
 682{
 683	u8 data;
 684
 685	int ret = ec_read(HP_OMEN_EC_THERMAL_PROFILE_OFFSET, &data);
 686
 687	if (ret)
 688		return ret;
 689
 690	return data;
 691}
 692
 693static int hp_wmi_fan_speed_max_set(int enabled)
 694{
 695	int ret;
 696
 697	ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_SET_QUERY, HPWMI_GM,
 698				   &enabled, sizeof(enabled), 0);
 699
 700	if (ret)
 701		return ret < 0 ? ret : -EINVAL;
 702
 703	return enabled;
 704}
 705
 706static int hp_wmi_fan_speed_reset(void)
 707{
 708	u8 fan_speed[2] = { HP_FAN_SPEED_AUTOMATIC, HP_FAN_SPEED_AUTOMATIC };
 709	int ret;
 710
 711	ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_SET_QUERY, HPWMI_GM,
 712				   &fan_speed, sizeof(fan_speed), 0);
 713
 714	return ret;
 715}
 716
 717static int hp_wmi_fan_speed_max_reset(void)
 718{
 719	int ret;
 720
 721	ret = hp_wmi_fan_speed_max_set(0);
 722	if (ret)
 723		return ret;
 724
 725	/* Disabling max fan speed on Victus s1xxx laptops needs a 2nd step: */
 726	ret = hp_wmi_fan_speed_reset();
 727	return ret;
 728}
 729
 730static int hp_wmi_fan_speed_max_get(void)
 731{
 732	int val = 0, ret;
 733
 734	ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_GET_QUERY, HPWMI_GM,
 735				   &val, zero_if_sup(val), sizeof(val));
 736
 737	if (ret)
 738		return ret < 0 ? ret : -EINVAL;
 739
 740	return val;
 741}
 742
 743static int __init hp_wmi_bios_2008_later(void)
 744{
 745	int state = 0;
 746	int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state,
 747				       zero_if_sup(state), sizeof(state));
 748	if (!ret)
 749		return 1;
 750
 751	return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
 752}
 753
 754static int __init hp_wmi_bios_2009_later(void)
 755{
 756	u8 state[128];
 757	int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
 758				       zero_if_sup(state), sizeof(state));
 759	if (!ret)
 760		return 1;
 761
 762	return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
 763}
 764
 765static int __init hp_wmi_enable_hotkeys(void)
 766{
 767	int value = 0x6e;
 768	int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value,
 769				       sizeof(value), 0);
 770
 771	return ret <= 0 ? ret : -EINVAL;
 772}
 773
 774static int hp_wmi_set_block(void *data, bool blocked)
 775{
 776	enum hp_wmi_radio r = (long)data;
 777	int query = BIT(r + 8) | ((!blocked) << r);
 778	int ret;
 779
 780	ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE,
 781				   &query, sizeof(query), 0);
 782
 783	return ret <= 0 ? ret : -EINVAL;
 784}
 785
 786static const struct rfkill_ops hp_wmi_rfkill_ops = {
 787	.set_block = hp_wmi_set_block,
 788};
 789
 790static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
 791{
 792	int mask = 0x200 << (r * 8);
 793
 794	int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
 795
 796	/* TBD: Pass error */
 797	WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
 798
 799	return !(wireless & mask);
 800}
 801
 802static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
 803{
 804	int mask = 0x800 << (r * 8);
 805
 806	int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
 807
 808	/* TBD: Pass error */
 809	WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
 810
 811	return !(wireless & mask);
 812}
 813
 814static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
 815{
 816	int rfkill_id = (int)(long)data;
 817	char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
 818	int ret;
 819
 820	ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE,
 821				   buffer, sizeof(buffer), 0);
 822
 823	return ret <= 0 ? ret : -EINVAL;
 824}
 825
 826static const struct rfkill_ops hp_wmi_rfkill2_ops = {
 827	.set_block = hp_wmi_rfkill2_set_block,
 828};
 829
 830static int hp_wmi_rfkill2_refresh(void)
 831{
 832	struct bios_rfkill2_state state;
 833	int err, i;
 834
 835	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
 836				   zero_if_sup(state), sizeof(state));
 837	if (err)
 838		return err;
 839
 840	for (i = 0; i < rfkill2_count; i++) {
 841		int num = rfkill2[i].num;
 842		struct bios_rfkill2_device_state *devstate;
 843
 844		devstate = &state.device[num];
 845
 846		if (num >= state.count ||
 847		    devstate->rfkill_id != rfkill2[i].id) {
 848			pr_warn("power configuration of the wireless devices unexpectedly changed\n");
 849			continue;
 850		}
 851
 852		rfkill_set_states(rfkill2[i].rfkill,
 853				  IS_SWBLOCKED(devstate->power),
 854				  IS_HWBLOCKED(devstate->power));
 855	}
 856
 857	return 0;
 858}
 859
 860static ssize_t display_show(struct device *dev, struct device_attribute *attr,
 861			    char *buf)
 862{
 863	int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY);
 864
 865	if (value < 0)
 866		return value;
 867	return sysfs_emit(buf, "%d\n", value);
 868}
 869
 870static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr,
 871			    char *buf)
 872{
 873	int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY);
 874
 875	if (value < 0)
 876		return value;
 877	return sysfs_emit(buf, "%d\n", value);
 878}
 879
 880static ssize_t als_show(struct device *dev, struct device_attribute *attr,
 881			char *buf)
 882{
 883	int value = hp_wmi_read_int(HPWMI_ALS_QUERY);
 884
 885	if (value < 0)
 886		return value;
 887	return sysfs_emit(buf, "%d\n", value);
 888}
 889
 890static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
 891			 char *buf)
 892{
 893	int value = hp_wmi_get_dock_state();
 894
 895	if (value < 0)
 896		return value;
 897	return sysfs_emit(buf, "%d\n", value);
 898}
 899
 900static ssize_t tablet_show(struct device *dev, struct device_attribute *attr,
 901			   char *buf)
 902{
 903	int value = hp_wmi_get_tablet_mode();
 904
 905	if (value < 0)
 906		return value;
 907	return sysfs_emit(buf, "%d\n", value);
 908}
 909
 910static ssize_t postcode_show(struct device *dev, struct device_attribute *attr,
 911			     char *buf)
 912{
 913	/* Get the POST error code of previous boot failure. */
 914	int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY);
 915
 916	if (value < 0)
 917		return value;
 918	return sysfs_emit(buf, "0x%x\n", value);
 919}
 920
 921static ssize_t als_store(struct device *dev, struct device_attribute *attr,
 922			 const char *buf, size_t count)
 923{
 924	u32 tmp;
 925	int ret;
 926
 927	ret = kstrtou32(buf, 10, &tmp);
 928	if (ret)
 929		return ret;
 930
 931	ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
 932				       sizeof(tmp), 0);
 933	if (ret)
 934		return ret < 0 ? ret : -EINVAL;
 935
 936	return count;
 937}
 938
 939static ssize_t postcode_store(struct device *dev, struct device_attribute *attr,
 940			      const char *buf, size_t count)
 941{
 942	u32 tmp = 1;
 943	bool clear;
 944	int ret;
 945
 946	ret = kstrtobool(buf, &clear);
 947	if (ret)
 948		return ret;
 949
 950	if (clear == false)
 951		return -EINVAL;
 952
 953	/* Clear the POST error code. It is kept until cleared. */
 954	ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp,
 955				       sizeof(tmp), 0);
 956	if (ret)
 957		return ret < 0 ? ret : -EINVAL;
 958
 959	return count;
 960}
 961
 962static int camera_shutter_input_setup(void)
 963{
 964	int err;
 965
 966	camera_shutter_input_dev = input_allocate_device();
 967	if (!camera_shutter_input_dev)
 968		return -ENOMEM;
 969
 970	camera_shutter_input_dev->name = "HP WMI camera shutter";
 971	camera_shutter_input_dev->phys = "wmi/input1";
 972	camera_shutter_input_dev->id.bustype = BUS_HOST;
 973
 974	__set_bit(EV_SW, camera_shutter_input_dev->evbit);
 975	__set_bit(SW_CAMERA_LENS_COVER, camera_shutter_input_dev->swbit);
 976
 977	err = input_register_device(camera_shutter_input_dev);
 978	if (err)
 979		goto err_free_dev;
 980
 981	return 0;
 982
 983 err_free_dev:
 984	input_free_device(camera_shutter_input_dev);
 985	camera_shutter_input_dev = NULL;
 986	return err;
 987}
 988
 989static DEVICE_ATTR_RO(display);
 990static DEVICE_ATTR_RO(hddtemp);
 991static DEVICE_ATTR_RW(als);
 992static DEVICE_ATTR_RO(dock);
 993static DEVICE_ATTR_RO(tablet);
 994static DEVICE_ATTR_RW(postcode);
 995
 996static struct attribute *hp_wmi_attrs[] = {
 997	&dev_attr_display.attr,
 998	&dev_attr_hddtemp.attr,
 999	&dev_attr_als.attr,
1000	&dev_attr_dock.attr,
1001	&dev_attr_tablet.attr,
1002	&dev_attr_postcode.attr,
1003	NULL,
1004};
1005ATTRIBUTE_GROUPS(hp_wmi);
1006
1007static void hp_wmi_notify(union acpi_object *obj, void *context)
1008{
1009	u32 event_id, event_data;
1010	u32 *location;
1011	int key_code;
1012
1013	if (!obj)
1014		return;
1015	if (obj->type != ACPI_TYPE_BUFFER) {
1016		pr_info("Unknown response received %d\n", obj->type);
1017		return;
1018	}
1019
1020	/*
1021	 * Depending on ACPI version the concatenation of id and event data
1022	 * inside _WED function will result in a 8 or 16 byte buffer.
1023	 */
1024	location = (u32 *)obj->buffer.pointer;
1025	if (obj->buffer.length == 8) {
1026		event_id = *location;
1027		event_data = *(location + 1);
1028	} else if (obj->buffer.length == 16) {
1029		event_id = *location;
1030		event_data = *(location + 2);
1031	} else {
1032		pr_info("Unknown buffer length %d\n", obj->buffer.length);
1033		return;
1034	}
1035
1036	switch (event_id) {
1037	case HPWMI_DOCK_EVENT:
1038		if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
1039			input_report_switch(hp_wmi_input_dev, SW_DOCK,
1040					    hp_wmi_get_dock_state());
1041		if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
1042			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
1043					    hp_wmi_get_tablet_mode());
1044		input_sync(hp_wmi_input_dev);
1045		break;
1046	case HPWMI_PARK_HDD:
1047		break;
1048	case HPWMI_SMART_ADAPTER:
1049		break;
1050	case HPWMI_BEZEL_BUTTON:
1051		key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
1052		if (key_code < 0)
1053			break;
1054
1055		if (!sparse_keymap_report_event(hp_wmi_input_dev,
1056						key_code, 1, true))
1057			pr_info("Unknown key code - 0x%x\n", key_code);
1058		break;
1059	case HPWMI_FN_P_HOTKEY:
1060		platform_profile_cycle();
1061		break;
1062	case HPWMI_OMEN_KEY:
1063		if (event_data) /* Only should be true for HP Omen */
1064			key_code = event_data;
1065		else
1066			key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
1067
1068		if (!sparse_keymap_report_event(hp_wmi_input_dev,
1069						key_code, 1, true))
1070			pr_info("Unknown key code - 0x%x\n", key_code);
1071		break;
1072	case HPWMI_WIRELESS:
1073		if (rfkill2_count) {
1074			hp_wmi_rfkill2_refresh();
1075			break;
1076		}
1077
1078		if (wifi_rfkill)
1079			rfkill_set_states(wifi_rfkill,
1080					  hp_wmi_get_sw_state(HPWMI_WIFI),
1081					  hp_wmi_get_hw_state(HPWMI_WIFI));
1082		if (bluetooth_rfkill)
1083			rfkill_set_states(bluetooth_rfkill,
1084					  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
1085					  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
1086		if (wwan_rfkill)
1087			rfkill_set_states(wwan_rfkill,
1088					  hp_wmi_get_sw_state(HPWMI_WWAN),
1089					  hp_wmi_get_hw_state(HPWMI_WWAN));
1090		break;
1091	case HPWMI_CPU_BATTERY_THROTTLE:
1092		pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
1093		break;
1094	case HPWMI_LOCK_SWITCH:
1095		break;
1096	case HPWMI_LID_SWITCH:
1097		break;
1098	case HPWMI_SCREEN_ROTATION:
1099		break;
1100	case HPWMI_COOLSENSE_SYSTEM_MOBILE:
1101		break;
1102	case HPWMI_COOLSENSE_SYSTEM_HOT:
1103		break;
1104	case HPWMI_PROXIMITY_SENSOR:
1105		break;
1106	case HPWMI_BACKLIT_KB_BRIGHTNESS:
1107		break;
1108	case HPWMI_PEAKSHIFT_PERIOD:
1109		break;
1110	case HPWMI_BATTERY_CHARGE_PERIOD:
1111		break;
1112	case HPWMI_SANITIZATION_MODE:
1113		break;
1114	case HPWMI_CAMERA_TOGGLE:
1115		if (!camera_shutter_input_dev)
1116			if (camera_shutter_input_setup()) {
1117				pr_err("Failed to setup camera shutter input device\n");
1118				break;
1119			}
1120		if (event_data == 0xff)
1121			input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 1);
1122		else if (event_data == 0xfe)
1123			input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 0);
1124		else
1125			pr_warn("Unknown camera shutter state - 0x%x\n", event_data);
1126		input_sync(camera_shutter_input_dev);
1127		break;
1128	case HPWMI_SMART_EXPERIENCE_APP:
1129		break;
1130	default:
1131		pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
1132		break;
1133	}
1134}
1135
1136static int __init hp_wmi_input_setup(void)
1137{
1138	acpi_status status;
1139	int err, val;
1140
1141	hp_wmi_input_dev = input_allocate_device();
1142	if (!hp_wmi_input_dev)
1143		return -ENOMEM;
1144
1145	hp_wmi_input_dev->name = "HP WMI hotkeys";
1146	hp_wmi_input_dev->phys = "wmi/input0";
1147	hp_wmi_input_dev->id.bustype = BUS_HOST;
1148
1149	__set_bit(EV_SW, hp_wmi_input_dev->evbit);
1150
1151	/* Dock */
1152	val = hp_wmi_get_dock_state();
1153	if (!(val < 0)) {
1154		__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
1155		input_report_switch(hp_wmi_input_dev, SW_DOCK, val);
1156	}
1157
1158	/* Tablet mode */
1159	val = hp_wmi_get_tablet_mode();
1160	if (!(val < 0)) {
1161		__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
1162		input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
1163	}
1164
1165	err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
1166	if (err)
1167		goto err_free_dev;
1168
1169	/* Set initial hardware state */
1170	input_sync(hp_wmi_input_dev);
1171
1172	if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later())
1173		hp_wmi_enable_hotkeys();
1174
1175	status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
1176	if (ACPI_FAILURE(status)) {
1177		err = -EIO;
1178		goto err_free_dev;
1179	}
1180
1181	err = input_register_device(hp_wmi_input_dev);
1182	if (err)
1183		goto err_uninstall_notifier;
1184
1185	return 0;
1186
1187 err_uninstall_notifier:
1188	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
1189 err_free_dev:
1190	input_free_device(hp_wmi_input_dev);
1191	return err;
1192}
1193
1194static void hp_wmi_input_destroy(void)
1195{
1196	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
1197	input_unregister_device(hp_wmi_input_dev);
1198}
1199
1200static int __init hp_wmi_rfkill_setup(struct platform_device *device)
1201{
1202	int err, wireless;
1203
1204	wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
1205	if (wireless < 0)
1206		return wireless;
1207
1208	err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless,
1209				   sizeof(wireless), 0);
1210	if (err)
1211		return err;
1212
1213	if (wireless & 0x1) {
1214		wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
1215					   RFKILL_TYPE_WLAN,
1216					   &hp_wmi_rfkill_ops,
1217					   (void *) HPWMI_WIFI);
1218		if (!wifi_rfkill)
1219			return -ENOMEM;
1220		rfkill_init_sw_state(wifi_rfkill,
1221				     hp_wmi_get_sw_state(HPWMI_WIFI));
1222		rfkill_set_hw_state(wifi_rfkill,
1223				    hp_wmi_get_hw_state(HPWMI_WIFI));
1224		err = rfkill_register(wifi_rfkill);
1225		if (err)
1226			goto register_wifi_error;
1227	}
1228
1229	if (wireless & 0x2) {
1230		bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
1231						RFKILL_TYPE_BLUETOOTH,
1232						&hp_wmi_rfkill_ops,
1233						(void *) HPWMI_BLUETOOTH);
1234		if (!bluetooth_rfkill) {
1235			err = -ENOMEM;
1236			goto register_bluetooth_error;
1237		}
1238		rfkill_init_sw_state(bluetooth_rfkill,
1239				     hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
1240		rfkill_set_hw_state(bluetooth_rfkill,
1241				    hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
1242		err = rfkill_register(bluetooth_rfkill);
1243		if (err)
1244			goto register_bluetooth_error;
1245	}
1246
1247	if (wireless & 0x4) {
1248		wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
1249					   RFKILL_TYPE_WWAN,
1250					   &hp_wmi_rfkill_ops,
1251					   (void *) HPWMI_WWAN);
1252		if (!wwan_rfkill) {
1253			err = -ENOMEM;
1254			goto register_wwan_error;
1255		}
1256		rfkill_init_sw_state(wwan_rfkill,
1257				     hp_wmi_get_sw_state(HPWMI_WWAN));
1258		rfkill_set_hw_state(wwan_rfkill,
1259				    hp_wmi_get_hw_state(HPWMI_WWAN));
1260		err = rfkill_register(wwan_rfkill);
1261		if (err)
1262			goto register_wwan_error;
1263	}
1264
1265	return 0;
1266
1267register_wwan_error:
1268	rfkill_destroy(wwan_rfkill);
1269	wwan_rfkill = NULL;
1270	if (bluetooth_rfkill)
1271		rfkill_unregister(bluetooth_rfkill);
1272register_bluetooth_error:
1273	rfkill_destroy(bluetooth_rfkill);
1274	bluetooth_rfkill = NULL;
1275	if (wifi_rfkill)
1276		rfkill_unregister(wifi_rfkill);
1277register_wifi_error:
1278	rfkill_destroy(wifi_rfkill);
1279	wifi_rfkill = NULL;
1280	return err;
1281}
1282
1283static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
1284{
1285	struct bios_rfkill2_state state;
1286	int err, i;
1287
1288	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
1289				   zero_if_sup(state), sizeof(state));
1290	if (err)
1291		return err < 0 ? err : -EINVAL;
1292
1293	if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
1294		pr_warn("unable to parse 0x1b query output\n");
1295		return -EINVAL;
1296	}
1297
1298	for (i = 0; i < state.count; i++) {
1299		struct rfkill *rfkill;
1300		enum rfkill_type type;
1301		char *name;
1302
1303		switch (state.device[i].radio_type) {
1304		case HPWMI_WIFI:
1305			type = RFKILL_TYPE_WLAN;
1306			name = "hp-wifi";
1307			break;
1308		case HPWMI_BLUETOOTH:
1309			type = RFKILL_TYPE_BLUETOOTH;
1310			name = "hp-bluetooth";
1311			break;
1312		case HPWMI_WWAN:
1313			type = RFKILL_TYPE_WWAN;
1314			name = "hp-wwan";
1315			break;
1316		case HPWMI_GPS:
1317			type = RFKILL_TYPE_GPS;
1318			name = "hp-gps";
1319			break;
1320		default:
1321			pr_warn("unknown device type 0x%x\n",
1322				state.device[i].radio_type);
1323			continue;
1324		}
1325
1326		if (!state.device[i].vendor_id) {
1327			pr_warn("zero device %d while %d reported\n",
1328				i, state.count);
1329			continue;
1330		}
1331
1332		rfkill = rfkill_alloc(name, &device->dev, type,
1333				      &hp_wmi_rfkill2_ops, (void *)(long)i);
1334		if (!rfkill) {
1335			err = -ENOMEM;
1336			goto fail;
1337		}
1338
1339		rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
1340		rfkill2[rfkill2_count].num = i;
1341		rfkill2[rfkill2_count].rfkill = rfkill;
1342
1343		rfkill_init_sw_state(rfkill,
1344				     IS_SWBLOCKED(state.device[i].power));
1345		rfkill_set_hw_state(rfkill,
1346				    IS_HWBLOCKED(state.device[i].power));
1347
1348		if (!(state.device[i].power & HPWMI_POWER_BIOS))
1349			pr_info("device %s blocked by BIOS\n", name);
1350
1351		err = rfkill_register(rfkill);
1352		if (err) {
1353			rfkill_destroy(rfkill);
1354			goto fail;
1355		}
1356
1357		rfkill2_count++;
1358	}
1359
1360	return 0;
1361fail:
1362	for (; rfkill2_count > 0; rfkill2_count--) {
1363		rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
1364		rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
1365	}
1366	return err;
1367}
1368
1369static int platform_profile_omen_get_ec(enum platform_profile_option *profile)
1370{
1371	int tp;
1372
1373	tp = omen_thermal_profile_get();
1374	if (tp < 0)
1375		return tp;
1376
1377	switch (tp) {
1378	case HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE:
1379	case HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE:
1380		*profile = PLATFORM_PROFILE_PERFORMANCE;
1381		break;
1382	case HP_OMEN_V0_THERMAL_PROFILE_DEFAULT:
1383	case HP_OMEN_V1_THERMAL_PROFILE_DEFAULT:
1384		*profile = PLATFORM_PROFILE_BALANCED;
1385		break;
1386	case HP_OMEN_V0_THERMAL_PROFILE_COOL:
1387	case HP_OMEN_V1_THERMAL_PROFILE_COOL:
1388		*profile = PLATFORM_PROFILE_COOL;
1389		break;
1390	default:
1391		return -EINVAL;
1392	}
1393
1394	return 0;
1395}
1396
1397static int platform_profile_omen_get(struct device *dev,
1398				     enum platform_profile_option *profile)
1399{
1400	/*
1401	 * We directly return the stored platform profile, as the embedded
1402	 * controller will not accept switching to the performance option when
1403	 * the conditions are not met (e.g. the laptop is not plugged in).
1404	 *
1405	 * If we directly return what the EC reports, the platform profile will
1406	 * immediately "switch back" to normal mode, which is against the
1407	 * expected behaviour from a userspace point of view, as described in
1408	 * the Platform Profile Section page of the kernel documentation.
1409	 *
1410	 * See also omen_powersource_event.
1411	 */
1412	guard(mutex)(&active_platform_profile_lock);
1413	*profile = active_platform_profile;
1414
1415	return 0;
1416}
1417
1418static bool has_omen_thermal_profile_ec_timer(void)
1419{
1420	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
1421
1422	if (!board_name)
1423		return false;
1424
1425	return match_string(omen_timed_thermal_profile_boards,
1426			    ARRAY_SIZE(omen_timed_thermal_profile_boards),
1427			    board_name) >= 0;
1428}
1429
1430inline int omen_thermal_profile_ec_flags_set(enum hp_thermal_profile_omen_flags flags)
1431{
1432	return ec_write(HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET, flags);
1433}
1434
1435inline int omen_thermal_profile_ec_timer_set(u8 value)
1436{
1437	return ec_write(HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET, value);
1438}
1439
1440static int platform_profile_omen_set_ec(enum platform_profile_option profile)
1441{
1442	int err, tp, tp_version;
1443	enum hp_thermal_profile_omen_flags flags = 0;
1444
1445	tp_version = omen_get_thermal_policy_version();
1446
1447	if (tp_version < 0 || tp_version > 1)
1448		return -EOPNOTSUPP;
1449
1450	switch (profile) {
1451	case PLATFORM_PROFILE_PERFORMANCE:
1452		if (tp_version == 0)
1453			tp = HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE;
1454		else
1455			tp = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE;
1456		break;
1457	case PLATFORM_PROFILE_BALANCED:
1458		if (tp_version == 0)
1459			tp = HP_OMEN_V0_THERMAL_PROFILE_DEFAULT;
1460		else
1461			tp = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT;
1462		break;
1463	case PLATFORM_PROFILE_COOL:
1464		if (tp_version == 0)
1465			tp = HP_OMEN_V0_THERMAL_PROFILE_COOL;
1466		else
1467			tp = HP_OMEN_V1_THERMAL_PROFILE_COOL;
1468		break;
1469	default:
1470		return -EOPNOTSUPP;
1471	}
1472
1473	err = omen_thermal_profile_set(tp);
1474	if (err < 0)
1475		return err;
1476
1477	if (has_omen_thermal_profile_ec_timer()) {
1478		err = omen_thermal_profile_ec_timer_set(0);
1479		if (err < 0)
1480			return err;
1481
1482		if (profile == PLATFORM_PROFILE_PERFORMANCE)
1483			flags = HP_OMEN_EC_FLAGS_NOTIMER |
1484				HP_OMEN_EC_FLAGS_TURBO;
1485
1486		err = omen_thermal_profile_ec_flags_set(flags);
1487		if (err < 0)
1488			return err;
1489	}
1490
1491	return 0;
1492}
1493
1494static int platform_profile_omen_set(struct device *dev,
1495				     enum platform_profile_option profile)
1496{
1497	int err;
1498
1499	guard(mutex)(&active_platform_profile_lock);
1500
1501	err = platform_profile_omen_set_ec(profile);
1502	if (err < 0)
1503		return err;
1504
1505	active_platform_profile = profile;
1506
1507	return 0;
1508}
1509
1510static int thermal_profile_get(void)
1511{
1512	return hp_wmi_read_int(HPWMI_THERMAL_PROFILE_QUERY);
1513}
1514
1515static int thermal_profile_set(int thermal_profile)
1516{
1517	return hp_wmi_perform_query(HPWMI_THERMAL_PROFILE_QUERY, HPWMI_WRITE, &thermal_profile,
1518							   sizeof(thermal_profile), 0);
1519}
1520
1521static int hp_wmi_platform_profile_get(struct device *dev,
1522					enum platform_profile_option *profile)
1523{
1524	int tp;
1525
1526	tp = thermal_profile_get();
1527	if (tp < 0)
1528		return tp;
1529
1530	switch (tp) {
1531	case HP_THERMAL_PROFILE_PERFORMANCE:
1532		*profile =  PLATFORM_PROFILE_PERFORMANCE;
1533		break;
1534	case HP_THERMAL_PROFILE_DEFAULT:
1535		*profile =  PLATFORM_PROFILE_BALANCED;
1536		break;
1537	case HP_THERMAL_PROFILE_COOL:
1538		*profile =  PLATFORM_PROFILE_COOL;
1539		break;
1540	case HP_THERMAL_PROFILE_QUIET:
1541		*profile = PLATFORM_PROFILE_QUIET;
1542		break;
1543	default:
1544		return -EINVAL;
1545	}
1546
1547	return 0;
1548}
1549
1550static int hp_wmi_platform_profile_set(struct device *dev,
1551					enum platform_profile_option profile)
1552{
1553	int err, tp;
1554
1555	switch (profile) {
1556	case PLATFORM_PROFILE_PERFORMANCE:
1557		tp =  HP_THERMAL_PROFILE_PERFORMANCE;
1558		break;
1559	case PLATFORM_PROFILE_BALANCED:
1560		tp =  HP_THERMAL_PROFILE_DEFAULT;
1561		break;
1562	case PLATFORM_PROFILE_COOL:
1563		tp =  HP_THERMAL_PROFILE_COOL;
1564		break;
1565	case PLATFORM_PROFILE_QUIET:
1566		tp = HP_THERMAL_PROFILE_QUIET;
1567		break;
1568	default:
1569		return -EOPNOTSUPP;
1570	}
1571
1572	err = thermal_profile_set(tp);
1573	if (err)
1574		return err;
1575
1576	return 0;
1577}
1578
1579static bool is_victus_thermal_profile(void)
1580{
1581	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
1582
1583	if (!board_name)
1584		return false;
1585
1586	return match_string(victus_thermal_profile_boards,
1587			    ARRAY_SIZE(victus_thermal_profile_boards),
1588			    board_name) >= 0;
1589}
1590
1591static int platform_profile_victus_get_ec(enum platform_profile_option *profile)
1592{
1593	int tp;
1594
1595	tp = omen_thermal_profile_get();
1596	if (tp < 0)
1597		return tp;
1598
1599	switch (tp) {
1600	case HP_VICTUS_THERMAL_PROFILE_PERFORMANCE:
1601		*profile = PLATFORM_PROFILE_PERFORMANCE;
1602		break;
1603	case HP_VICTUS_THERMAL_PROFILE_DEFAULT:
1604		*profile = PLATFORM_PROFILE_BALANCED;
1605		break;
1606	case HP_VICTUS_THERMAL_PROFILE_QUIET:
1607		*profile = PLATFORM_PROFILE_QUIET;
1608		break;
1609	default:
1610		return -EOPNOTSUPP;
1611	}
1612
1613	return 0;
1614}
1615
1616static int platform_profile_victus_get(struct device *dev,
1617				       enum platform_profile_option *profile)
1618{
1619	/* Same behaviour as platform_profile_omen_get */
1620	return platform_profile_omen_get(dev, profile);
1621}
1622
1623static int platform_profile_victus_set_ec(enum platform_profile_option profile)
1624{
1625	int err, tp;
1626
1627	switch (profile) {
1628	case PLATFORM_PROFILE_PERFORMANCE:
1629		tp = HP_VICTUS_THERMAL_PROFILE_PERFORMANCE;
1630		break;
1631	case PLATFORM_PROFILE_BALANCED:
1632		tp = HP_VICTUS_THERMAL_PROFILE_DEFAULT;
1633		break;
1634	case PLATFORM_PROFILE_QUIET:
1635		tp = HP_VICTUS_THERMAL_PROFILE_QUIET;
1636		break;
1637	default:
1638		return -EOPNOTSUPP;
1639	}
1640
1641	err = omen_thermal_profile_set(tp);
1642	if (err < 0)
1643		return err;
1644
1645	return 0;
1646}
1647
1648static bool is_victus_s_thermal_profile(void)
1649{
1650	/* Initialised in driver init, hence safe to use here */
1651	return is_victus_s_board;
1652}
1653
1654static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable,
1655					    bool *ppab_enable,
1656					    u8 *dstate,
1657					    u8 *gpu_slowdown_temp)
1658{
1659	struct victus_gpu_power_modes gpu_power_modes;
1660	int ret;
1661
1662	ret = hp_wmi_perform_query(HPWMI_GET_GPU_THERMAL_MODES_QUERY, HPWMI_GM,
1663				   &gpu_power_modes, sizeof(gpu_power_modes),
1664				   sizeof(gpu_power_modes));
1665	if (ret == 0) {
1666		*ctgp_enable = gpu_power_modes.ctgp_enable ? true : false;
1667		*ppab_enable = gpu_power_modes.ppab_enable ? true : false;
1668		*dstate = gpu_power_modes.dstate;
1669		*gpu_slowdown_temp = gpu_power_modes.gpu_slowdown_temp;
1670	}
1671
1672	return ret;
1673}
1674
1675static int victus_s_gpu_thermal_profile_set(bool ctgp_enable,
1676					    bool ppab_enable,
1677					    u8 dstate)
1678{
1679	struct victus_gpu_power_modes gpu_power_modes;
1680	int ret;
1681
1682	bool current_ctgp_state, current_ppab_state;
1683	u8 current_dstate, current_gpu_slowdown_temp;
1684
1685	/* Retrieving GPU slowdown temperature, in order to keep it unchanged */
1686	ret = victus_s_gpu_thermal_profile_get(&current_ctgp_state,
1687					       &current_ppab_state,
1688					       &current_dstate,
1689					       &current_gpu_slowdown_temp);
1690	if (ret < 0) {
1691		pr_warn("GPU modes not updated, unable to get slowdown temp\n");
1692		return ret;
1693	}
1694
1695	gpu_power_modes.ctgp_enable = ctgp_enable ? 0x01 : 0x00;
1696	gpu_power_modes.ppab_enable = ppab_enable ? 0x01 : 0x00;
1697	gpu_power_modes.dstate = dstate;
1698	gpu_power_modes.gpu_slowdown_temp = current_gpu_slowdown_temp;
1699
1700
1701	ret = hp_wmi_perform_query(HPWMI_SET_GPU_THERMAL_MODES_QUERY, HPWMI_GM,
1702				   &gpu_power_modes, sizeof(gpu_power_modes), 0);
1703
1704	return ret;
1705}
1706
1707/* Note: HP_POWER_LIMIT_DEFAULT can be used to restore default PL1 and PL2 */
1708static int victus_s_set_cpu_pl1_pl2(u8 pl1, u8 pl2)
1709{
1710	struct victus_power_limits power_limits;
1711	int ret;
1712
1713	/* We need to know both PL1 and PL2 values in order to check them */
1714	if (pl1 == HP_POWER_LIMIT_NO_CHANGE || pl2 == HP_POWER_LIMIT_NO_CHANGE)
1715		return -EINVAL;
1716
1717	/* PL2 is not supposed to be lower than PL1 */
1718	if (pl2 < pl1)
1719		return -EINVAL;
1720
1721	power_limits.pl1 = pl1;
1722	power_limits.pl2 = pl2;
1723	power_limits.pl4 = HP_POWER_LIMIT_NO_CHANGE;
1724	power_limits.cpu_gpu_concurrent_limit = HP_POWER_LIMIT_NO_CHANGE;
1725
1726	ret = hp_wmi_perform_query(HPWMI_SET_POWER_LIMITS_QUERY, HPWMI_GM,
1727				   &power_limits, sizeof(power_limits), 0);
1728
1729	return ret;
1730}
1731
1732static int platform_profile_victus_s_set_ec(enum platform_profile_option profile)
1733{
1734	struct thermal_profile_params *params;
1735	bool gpu_ctgp_enable, gpu_ppab_enable;
1736	u8 gpu_dstate; /* Test shows 1 = 100%, 2 = 50%, 3 = 25%, 4 = 12.5% */
1737	int err, tp;
1738
1739	params = active_thermal_profile_params;
1740	if (!params)
1741		return -ENODEV;
1742
1743	switch (profile) {
1744	case PLATFORM_PROFILE_PERFORMANCE:
1745		tp = params->performance;
1746		gpu_ctgp_enable = true;
1747		gpu_ppab_enable = true;
1748		gpu_dstate = 1;
1749		break;
1750	case PLATFORM_PROFILE_BALANCED:
1751		tp = params->balanced;
1752		gpu_ctgp_enable = false;
1753		gpu_ppab_enable = true;
1754		gpu_dstate = 1;
1755		break;
1756	case PLATFORM_PROFILE_LOW_POWER:
1757		tp = params->low_power;
1758		gpu_ctgp_enable = false;
1759		gpu_ppab_enable = false;
1760		gpu_dstate = 1;
1761		break;
1762	default:
1763		return -EOPNOTSUPP;
1764	}
1765
1766	hp_wmi_get_fan_count_userdefine_trigger();
1767
1768	err = omen_thermal_profile_set(tp);
1769	if (err < 0) {
1770		pr_err("Failed to set platform profile %d: %d\n", profile, err);
1771		return err;
1772	}
1773
1774	err = victus_s_gpu_thermal_profile_set(gpu_ctgp_enable,
1775					       gpu_ppab_enable,
1776					       gpu_dstate);
1777	if (err < 0) {
1778		pr_err("Failed to set GPU profile %d: %d\n", profile, err);
1779		return err;
1780	}
1781
1782	return 0;
1783}
1784
1785static int platform_profile_victus_s_set(struct device *dev,
1786					 enum platform_profile_option profile)
1787{
1788	int err;
1789
1790	guard(mutex)(&active_platform_profile_lock);
1791
1792	err = platform_profile_victus_s_set_ec(profile);
1793	if (err < 0)
1794		return err;
1795
1796	active_platform_profile = profile;
1797
1798	return 0;
1799}
1800
1801static int platform_profile_victus_set(struct device *dev,
1802				       enum platform_profile_option profile)
1803{
1804	int err;
1805
1806	guard(mutex)(&active_platform_profile_lock);
1807
1808	err = platform_profile_victus_set_ec(profile);
1809	if (err < 0)
1810		return err;
1811
1812	active_platform_profile = profile;
1813
1814	return 0;
1815}
1816
1817static int hp_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
1818{
1819	if (is_omen_thermal_profile()) {
1820		set_bit(PLATFORM_PROFILE_COOL, choices);
1821	} else if (is_victus_thermal_profile()) {
1822		set_bit(PLATFORM_PROFILE_QUIET, choices);
1823	} else if (is_victus_s_thermal_profile()) {
1824		/* Adding an equivalent to HP Omen software ECO mode: */
1825		set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
1826	} else {
1827		set_bit(PLATFORM_PROFILE_QUIET, choices);
1828		set_bit(PLATFORM_PROFILE_COOL, choices);
1829	}
1830
1831	set_bit(PLATFORM_PROFILE_BALANCED, choices);
1832	set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
1833
1834	return 0;
1835}
1836
1837static int omen_powersource_event(struct notifier_block *nb,
1838				  unsigned long value,
1839				  void *data)
1840{
1841	struct acpi_bus_event *event_entry = data;
1842	enum platform_profile_option actual_profile;
1843	int err;
1844
1845	if (strcmp(event_entry->device_class, ACPI_AC_CLASS) != 0)
1846		return NOTIFY_DONE;
1847
1848	pr_debug("Received power source device event\n");
1849
1850	guard(mutex)(&active_platform_profile_lock);
1851
1852	/*
1853	 * This handler can only be called on Omen and Victus models, so
1854	 * there's no need to call is_victus_thermal_profile() here.
1855	 */
1856	if (is_omen_thermal_profile())
1857		err = platform_profile_omen_get_ec(&actual_profile);
1858	else
1859		err = platform_profile_victus_get_ec(&actual_profile);
1860
1861	if (err < 0) {
1862		/*
1863		 * Although we failed to get the current platform profile, we
1864		 * still want the other event consumers to process it.
1865		 */
1866		pr_warn("Failed to read current platform profile (%d)\n", err);
1867		return NOTIFY_DONE;
1868	}
1869
1870	/*
1871	 * If we're back on AC and that the user-chosen power profile is
1872	 * different from what the EC reports, we restore the user-chosen
1873	 * one.
1874	 */
1875	if (power_supply_is_system_supplied() <= 0 ||
1876	    active_platform_profile == actual_profile) {
1877		pr_debug("Platform profile update skipped, conditions unmet\n");
1878		return NOTIFY_DONE;
1879	}
1880
1881	if (is_omen_thermal_profile())
1882		err = platform_profile_omen_set_ec(active_platform_profile);
1883	else
1884		err = platform_profile_victus_set_ec(active_platform_profile);
1885
1886	if (err < 0) {
1887		pr_warn("Failed to restore platform profile (%d)\n", err);
1888		return NOTIFY_DONE;
1889	}
1890
1891	return NOTIFY_OK;
1892}
1893
1894static int victus_s_powersource_event(struct notifier_block *nb,
1895				      unsigned long value,
1896				      void *data)
1897{
1898	struct acpi_bus_event *event_entry = data;
1899	int err;
1900
1901	if (strcmp(event_entry->device_class, ACPI_AC_CLASS) != 0)
1902		return NOTIFY_DONE;
1903
1904	pr_debug("Received power source device event\n");
1905
1906	/*
1907	 * Switching to battery power source while Performance mode is active
1908	 * needs manual triggering of CPU power limits. Same goes when switching
1909	 * to AC power source while Performance mode is active. Other modes
1910	 * however are automatically behaving without any manual action.
1911	 * Seen on HP 16-s1034nf (board 8C9C) with F.11 and F.13 BIOS versions.
1912	 */
1913
1914	if (active_platform_profile == PLATFORM_PROFILE_PERFORMANCE) {
1915		pr_debug("Triggering CPU PL1/PL2 actualization\n");
1916		err = victus_s_set_cpu_pl1_pl2(HP_POWER_LIMIT_DEFAULT,
1917					       HP_POWER_LIMIT_DEFAULT);
1918		if (err)
1919			pr_warn("Failed to actualize power limits: %d\n", err);
1920
1921		return NOTIFY_DONE;
1922	}
1923
1924	return NOTIFY_OK;
1925}
1926
1927static int omen_register_powersource_event_handler(void)
1928{
1929	int err;
1930
1931	platform_power_source_nb.notifier_call = omen_powersource_event;
1932	err = register_acpi_notifier(&platform_power_source_nb);
1933
1934	if (err < 0) {
1935		pr_warn("Failed to install ACPI power source notify handler\n");
1936		return err;
1937	}
1938
1939	return 0;
1940}
1941
1942static int victus_s_register_powersource_event_handler(void)
1943{
1944	int err;
1945
1946	platform_power_source_nb.notifier_call = victus_s_powersource_event;
1947	err = register_acpi_notifier(&platform_power_source_nb);
1948	if (err < 0) {
1949		pr_warn("Failed to install ACPI power source notify handler\n");
1950		return err;
1951	}
1952
1953	return 0;
1954}
1955
1956static inline void omen_unregister_powersource_event_handler(void)
1957{
1958	unregister_acpi_notifier(&platform_power_source_nb);
1959}
1960
1961static inline void victus_s_unregister_powersource_event_handler(void)
1962{
1963	unregister_acpi_notifier(&platform_power_source_nb);
1964}
1965
1966static const struct platform_profile_ops platform_profile_omen_ops = {
1967	.probe = hp_wmi_platform_profile_probe,
1968	.profile_get = platform_profile_omen_get,
1969	.profile_set = platform_profile_omen_set,
1970};
1971
1972static const struct platform_profile_ops platform_profile_victus_ops = {
1973	.probe = hp_wmi_platform_profile_probe,
1974	.profile_get = platform_profile_victus_get,
1975	.profile_set = platform_profile_victus_set,
1976};
1977
1978static const struct platform_profile_ops platform_profile_victus_s_ops = {
1979	.probe = hp_wmi_platform_profile_probe,
1980	.profile_get = platform_profile_omen_get,
1981	.profile_set = platform_profile_victus_s_set,
1982};
1983
1984static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
1985	.probe = hp_wmi_platform_profile_probe,
1986	.profile_get = hp_wmi_platform_profile_get,
1987	.profile_set = hp_wmi_platform_profile_set,
1988};
1989
1990static int thermal_profile_setup(struct platform_device *device)
1991{
1992	const struct platform_profile_ops *ops;
1993	int err, tp;
1994
1995	if (is_omen_thermal_profile()) {
1996		err = platform_profile_omen_get_ec(&active_platform_profile);
1997		if (err < 0)
1998			return err;
1999
2000		/*
2001		 * call thermal profile write command to ensure that the
2002		 * firmware correctly sets the OEM variables
2003		 */
2004		err = platform_profile_omen_set_ec(active_platform_profile);
2005		if (err < 0)
2006			return err;
2007
2008		ops = &platform_profile_omen_ops;
2009	} else if (is_victus_thermal_profile()) {
2010		err = platform_profile_victus_get_ec(&active_platform_profile);
2011		if (err < 0)
2012			return err;
2013
2014		/*
2015		 * call thermal profile write command to ensure that the
2016		 * firmware correctly sets the OEM variables
2017		 */
2018		err = platform_profile_victus_set_ec(active_platform_profile);
2019		if (err < 0)
2020			return err;
2021
2022		ops = &platform_profile_victus_ops;
2023	} else if (is_victus_s_thermal_profile()) {
2024		/*
2025		 * Being unable to retrieve laptop's current thermal profile,
2026		 * during this setup, we set it to Balanced by default.
2027		 */
2028		active_platform_profile = PLATFORM_PROFILE_BALANCED;
2029
2030		err = platform_profile_victus_s_set_ec(active_platform_profile);
2031		if (err < 0)
2032			return err;
2033
2034		ops = &platform_profile_victus_s_ops;
2035	} else {
2036		tp = thermal_profile_get();
2037
2038		if (tp < 0)
2039			return tp;
2040
2041		/*
2042		 * call thermal profile write command to ensure that the
2043		 * firmware correctly sets the OEM variables for the DPTF
2044		 */
2045		err = thermal_profile_set(tp);
2046		if (err)
2047			return err;
2048
2049		ops = &hp_wmi_platform_profile_ops;
2050	}
2051
2052	platform_profile_device = devm_platform_profile_register(&device->dev, "hp-wmi",
2053								 NULL, ops);
2054	if (IS_ERR(platform_profile_device))
2055		return PTR_ERR(platform_profile_device);
2056
2057	pr_info("Registered as platform profile handler\n");
2058	platform_profile_support = true;
2059
2060	return 0;
2061}
2062
2063static int hp_wmi_hwmon_init(void);
2064
2065static int __init hp_wmi_bios_setup(struct platform_device *device)
2066{
2067	int err;
2068	/* clear detected rfkill devices */
2069	wifi_rfkill = NULL;
2070	bluetooth_rfkill = NULL;
2071	wwan_rfkill = NULL;
2072	rfkill2_count = 0;
2073
2074	/*
2075	 * In pre-2009 BIOS, command 1Bh return 0x4 to indicate that
2076	 * BIOS no longer controls the power for the wireless
2077	 * devices. All features supported by this command will no
2078	 * longer be supported.
2079	 */
2080	if (!hp_wmi_bios_2009_later()) {
2081		if (hp_wmi_rfkill_setup(device))
2082			hp_wmi_rfkill2_setup(device);
2083	}
2084
2085	err = hp_wmi_hwmon_init();
2086
2087	if (err < 0)
2088		return err;
2089
2090	thermal_profile_setup(device);
2091
2092	return 0;
2093}
2094
2095static void __exit hp_wmi_bios_remove(struct platform_device *device)
2096{
2097	int i;
2098
2099	for (i = 0; i < rfkill2_count; i++) {
2100		rfkill_unregister(rfkill2[i].rfkill);
2101		rfkill_destroy(rfkill2[i].rfkill);
2102	}
2103
2104	if (wifi_rfkill) {
2105		rfkill_unregister(wifi_rfkill);
2106		rfkill_destroy(wifi_rfkill);
2107	}
2108	if (bluetooth_rfkill) {
2109		rfkill_unregister(bluetooth_rfkill);
2110		rfkill_destroy(bluetooth_rfkill);
2111	}
2112	if (wwan_rfkill) {
2113		rfkill_unregister(wwan_rfkill);
2114		rfkill_destroy(wwan_rfkill);
2115	}
2116}
2117
2118static int hp_wmi_resume_handler(struct device *device)
2119{
2120	/*
2121	 * Hardware state may have changed while suspended, so trigger
2122	 * input events for the current state. As this is a switch,
2123	 * the input layer will only actually pass it on if the state
2124	 * changed.
2125	 */
2126	if (hp_wmi_input_dev) {
2127		if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
2128			input_report_switch(hp_wmi_input_dev, SW_DOCK,
2129					    hp_wmi_get_dock_state());
2130		if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
2131			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
2132					    hp_wmi_get_tablet_mode());
2133		input_sync(hp_wmi_input_dev);
2134	}
2135
2136	if (rfkill2_count)
2137		hp_wmi_rfkill2_refresh();
2138
2139	if (wifi_rfkill)
2140		rfkill_set_states(wifi_rfkill,
2141				  hp_wmi_get_sw_state(HPWMI_WIFI),
2142				  hp_wmi_get_hw_state(HPWMI_WIFI));
2143	if (bluetooth_rfkill)
2144		rfkill_set_states(bluetooth_rfkill,
2145				  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
2146				  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
2147	if (wwan_rfkill)
2148		rfkill_set_states(wwan_rfkill,
2149				  hp_wmi_get_sw_state(HPWMI_WWAN),
2150				  hp_wmi_get_hw_state(HPWMI_WWAN));
2151
2152	return 0;
2153}
2154
2155static const struct dev_pm_ops hp_wmi_pm_ops = {
2156	.resume  = hp_wmi_resume_handler,
2157	.restore  = hp_wmi_resume_handler,
2158};
2159
2160/*
2161 * hp_wmi_bios_remove() lives in .exit.text. For drivers registered via
2162 * module_platform_driver_probe() this is ok because they cannot get unbound at
2163 * runtime. So mark the driver struct with __refdata to prevent modpost
2164 * triggering a section mismatch warning.
2165 */
2166static struct platform_driver hp_wmi_driver __refdata = {
2167	.driver = {
2168		.name = "hp-wmi",
2169		.pm = &hp_wmi_pm_ops,
2170		.dev_groups = hp_wmi_groups,
2171	},
2172	.remove = __exit_p(hp_wmi_bios_remove),
2173};
2174
2175static umode_t hp_wmi_hwmon_is_visible(const void *data,
2176				       enum hwmon_sensor_types type,
2177				       u32 attr, int channel)
2178{
2179	switch (type) {
2180	case hwmon_pwm:
2181		return 0644;
2182	case hwmon_fan:
2183		if (is_victus_s_thermal_profile()) {
2184			if (hp_wmi_get_fan_speed_victus_s(channel) >= 0)
2185				return 0444;
2186		} else {
2187			if (hp_wmi_get_fan_speed(channel) >= 0)
2188				return 0444;
2189		}
2190		break;
2191	default:
2192		return 0;
2193	}
2194
2195	return 0;
2196}
2197
2198static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
2199			     u32 attr, int channel, long *val)
2200{
2201	int ret;
2202
2203	switch (type) {
2204	case hwmon_fan:
2205		if (is_victus_s_thermal_profile())
2206			ret = hp_wmi_get_fan_speed_victus_s(channel);
2207		else
2208			ret = hp_wmi_get_fan_speed(channel);
2209		if (ret < 0)
2210			return ret;
2211		*val = ret;
2212		return 0;
2213	case hwmon_pwm:
2214		switch (hp_wmi_fan_speed_max_get()) {
2215		case 0:
2216			/* 0 is automatic fan, which is 2 for hwmon */
2217			*val = 2;
2218			return 0;
2219		case 1:
2220			/* 1 is max fan, which is 0
2221			 * (no fan speed control) for hwmon
2222			 */
2223			*val = 0;
2224			return 0;
2225		default:
2226			/* shouldn't happen */
2227			return -ENODATA;
2228		}
2229	default:
2230		return -EINVAL;
2231	}
2232}
2233
2234static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
2235			      u32 attr, int channel, long val)
2236{
2237	switch (type) {
2238	case hwmon_pwm:
2239		switch (val) {
2240		case 0:
2241			if (is_victus_s_thermal_profile())
2242				hp_wmi_get_fan_count_userdefine_trigger();
2243			/* 0 is no fan speed control (max), which is 1 for us */
2244			return hp_wmi_fan_speed_max_set(1);
2245		case 2:
2246			/* 2 is automatic speed control, which is 0 for us */
2247			if (is_victus_s_thermal_profile()) {
2248				hp_wmi_get_fan_count_userdefine_trigger();
2249				return hp_wmi_fan_speed_max_reset();
2250			} else
2251				return hp_wmi_fan_speed_max_set(0);
2252		default:
2253			/* we don't support manual fan speed control */
2254			return -EINVAL;
2255		}
2256	default:
2257		return -EOPNOTSUPP;
2258	}
2259}
2260
2261static const struct hwmon_channel_info * const info[] = {
2262	HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT),
2263	HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE),
2264	NULL
2265};
2266
2267static const struct hwmon_ops ops = {
2268	.is_visible = hp_wmi_hwmon_is_visible,
2269	.read = hp_wmi_hwmon_read,
2270	.write = hp_wmi_hwmon_write,
2271};
2272
2273static const struct hwmon_chip_info chip_info = {
2274	.ops = &ops,
2275	.info = info,
2276};
2277
2278static int hp_wmi_hwmon_init(void)
2279{
2280	struct device *dev = &hp_wmi_platform_dev->dev;
2281	struct device *hwmon;
2282
2283	hwmon = devm_hwmon_device_register_with_info(dev, "hp", &hp_wmi_driver,
2284						     &chip_info, NULL);
2285
2286	if (IS_ERR(hwmon)) {
2287		dev_err(dev, "Could not register hp hwmon device\n");
2288		return PTR_ERR(hwmon);
2289	}
2290
2291	return 0;
2292}
2293
2294static void __init setup_active_thermal_profile_params(void)
2295{
2296	const struct dmi_system_id *id;
2297
2298	/*
2299	 * Currently only victus_s devices use the
2300	 * active_thermal_profile_params
2301	 */
2302	id = dmi_first_match(victus_s_thermal_profile_boards);
2303	if (id) {
2304		/*
2305		 * Marking this boolean is required to ensure that
2306		 * is_victus_s_thermal_profile() behaves like a valid
2307		 * wrapper.
2308		 */
2309		is_victus_s_board = true;
2310		active_thermal_profile_params = id->driver_data;
2311	}
2312}
2313
2314static int __init hp_wmi_init(void)
2315{
2316	int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
2317	int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
2318	int err, tmp = 0;
2319
2320	if (!bios_capable && !event_capable)
2321		return -ENODEV;
2322
2323	if (hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, HPWMI_READ, &tmp,
2324				 sizeof(tmp), sizeof(tmp)) == HPWMI_RET_INVALID_PARAMETERS)
2325		zero_insize_support = true;
2326
2327	if (event_capable) {
2328		err = hp_wmi_input_setup();
2329		if (err)
2330			return err;
2331	}
2332
2333	if (bios_capable) {
2334		hp_wmi_platform_dev =
2335			platform_device_register_simple("hp-wmi", PLATFORM_DEVID_NONE, NULL, 0);
2336		if (IS_ERR(hp_wmi_platform_dev)) {
2337			err = PTR_ERR(hp_wmi_platform_dev);
2338			goto err_destroy_input;
2339		}
2340
2341		/*
2342		 * Setup active board's thermal profile parameters before
2343		 * starting platform driver probe.
2344		 */
2345		setup_active_thermal_profile_params();
2346		err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup);
2347		if (err)
2348			goto err_unregister_device;
2349	}
2350
2351	if (is_omen_thermal_profile() || is_victus_thermal_profile()) {
2352		err = omen_register_powersource_event_handler();
2353		if (err)
2354			goto err_unregister_device;
2355	} else if (is_victus_s_thermal_profile()) {
2356		err = victus_s_register_powersource_event_handler();
2357		if (err)
2358			goto err_unregister_device;
2359	}
2360
2361	return 0;
2362
2363err_unregister_device:
2364	platform_device_unregister(hp_wmi_platform_dev);
2365err_destroy_input:
2366	if (event_capable)
2367		hp_wmi_input_destroy();
2368
2369	return err;
2370}
2371module_init(hp_wmi_init);
2372
2373static void __exit hp_wmi_exit(void)
2374{
2375	if (is_omen_thermal_profile() || is_victus_thermal_profile())
2376		omen_unregister_powersource_event_handler();
2377
2378	if (is_victus_s_thermal_profile())
2379		victus_s_unregister_powersource_event_handler();
2380
2381	if (wmi_has_guid(HPWMI_EVENT_GUID))
2382		hp_wmi_input_destroy();
2383
2384	if (camera_shutter_input_dev)
2385		input_unregister_device(camera_shutter_input_dev);
2386
2387	if (hp_wmi_platform_dev) {
2388		platform_device_unregister(hp_wmi_platform_dev);
2389		platform_driver_unregister(&hp_wmi_driver);
2390	}
2391}
2392module_exit(hp_wmi_exit);
~/ Read-only file preview.