Linux Audio

Check our new training course

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