18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * HP WMI hotkeys
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2008 Red Hat <mjg@redhat.com>
68c2ecf20Sopenharmony_ci * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Portions based on wistron_btns.c:
98c2ecf20Sopenharmony_ci * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
108c2ecf20Sopenharmony_ci * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
118c2ecf20Sopenharmony_ci * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/kernel.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/init.h>
198c2ecf20Sopenharmony_ci#include <linux/slab.h>
208c2ecf20Sopenharmony_ci#include <linux/types.h>
218c2ecf20Sopenharmony_ci#include <linux/input.h>
228c2ecf20Sopenharmony_ci#include <linux/input/sparse-keymap.h>
238c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
248c2ecf20Sopenharmony_ci#include <linux/acpi.h>
258c2ecf20Sopenharmony_ci#include <linux/rfkill.h>
268c2ecf20Sopenharmony_ci#include <linux/string.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciMODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>");
298c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("HP laptop WMI hotkeys driver");
308c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ciMODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
338c2ecf20Sopenharmony_ciMODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic int enable_tablet_mode_sw = -1;
368c2ecf20Sopenharmony_cimodule_param(enable_tablet_mode_sw, int, 0444);
378c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enable_tablet_mode_sw, "Enable SW_TABLET_MODE reporting (-1=auto, 0=no, 1=yes)");
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
408c2ecf20Sopenharmony_ci#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cienum hp_wmi_radio {
438c2ecf20Sopenharmony_ci	HPWMI_WIFI	= 0x0,
448c2ecf20Sopenharmony_ci	HPWMI_BLUETOOTH	= 0x1,
458c2ecf20Sopenharmony_ci	HPWMI_WWAN	= 0x2,
468c2ecf20Sopenharmony_ci	HPWMI_GPS	= 0x3,
478c2ecf20Sopenharmony_ci};
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cienum hp_wmi_event_ids {
508c2ecf20Sopenharmony_ci	HPWMI_DOCK_EVENT		= 0x01,
518c2ecf20Sopenharmony_ci	HPWMI_PARK_HDD			= 0x02,
528c2ecf20Sopenharmony_ci	HPWMI_SMART_ADAPTER		= 0x03,
538c2ecf20Sopenharmony_ci	HPWMI_BEZEL_BUTTON		= 0x04,
548c2ecf20Sopenharmony_ci	HPWMI_WIRELESS			= 0x05,
558c2ecf20Sopenharmony_ci	HPWMI_CPU_BATTERY_THROTTLE	= 0x06,
568c2ecf20Sopenharmony_ci	HPWMI_LOCK_SWITCH		= 0x07,
578c2ecf20Sopenharmony_ci	HPWMI_LID_SWITCH		= 0x08,
588c2ecf20Sopenharmony_ci	HPWMI_SCREEN_ROTATION		= 0x09,
598c2ecf20Sopenharmony_ci	HPWMI_COOLSENSE_SYSTEM_MOBILE	= 0x0A,
608c2ecf20Sopenharmony_ci	HPWMI_COOLSENSE_SYSTEM_HOT	= 0x0B,
618c2ecf20Sopenharmony_ci	HPWMI_PROXIMITY_SENSOR		= 0x0C,
628c2ecf20Sopenharmony_ci	HPWMI_BACKLIT_KB_BRIGHTNESS	= 0x0D,
638c2ecf20Sopenharmony_ci	HPWMI_PEAKSHIFT_PERIOD		= 0x0F,
648c2ecf20Sopenharmony_ci	HPWMI_BATTERY_CHARGE_PERIOD	= 0x10,
658c2ecf20Sopenharmony_ci	HPWMI_SANITIZATION_MODE		= 0x17,
668c2ecf20Sopenharmony_ci	HPWMI_SMART_EXPERIENCE_APP	= 0x21,
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistruct bios_args {
708c2ecf20Sopenharmony_ci	u32 signature;
718c2ecf20Sopenharmony_ci	u32 command;
728c2ecf20Sopenharmony_ci	u32 commandtype;
738c2ecf20Sopenharmony_ci	u32 datasize;
748c2ecf20Sopenharmony_ci	u8 data[128];
758c2ecf20Sopenharmony_ci};
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cienum hp_wmi_commandtype {
788c2ecf20Sopenharmony_ci	HPWMI_DISPLAY_QUERY		= 0x01,
798c2ecf20Sopenharmony_ci	HPWMI_HDDTEMP_QUERY		= 0x02,
808c2ecf20Sopenharmony_ci	HPWMI_ALS_QUERY			= 0x03,
818c2ecf20Sopenharmony_ci	HPWMI_HARDWARE_QUERY		= 0x04,
828c2ecf20Sopenharmony_ci	HPWMI_WIRELESS_QUERY		= 0x05,
838c2ecf20Sopenharmony_ci	HPWMI_BATTERY_QUERY		= 0x07,
848c2ecf20Sopenharmony_ci	HPWMI_BIOS_QUERY		= 0x09,
858c2ecf20Sopenharmony_ci	HPWMI_FEATURE_QUERY		= 0x0b,
868c2ecf20Sopenharmony_ci	HPWMI_HOTKEY_QUERY		= 0x0c,
878c2ecf20Sopenharmony_ci	HPWMI_FEATURE2_QUERY		= 0x0d,
888c2ecf20Sopenharmony_ci	HPWMI_WIRELESS2_QUERY		= 0x1b,
898c2ecf20Sopenharmony_ci	HPWMI_POSTCODEERROR_QUERY	= 0x2a,
908c2ecf20Sopenharmony_ci	HPWMI_THERMAL_POLICY_QUERY	= 0x4c,
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cienum hp_wmi_command {
948c2ecf20Sopenharmony_ci	HPWMI_READ	= 0x01,
958c2ecf20Sopenharmony_ci	HPWMI_WRITE	= 0x02,
968c2ecf20Sopenharmony_ci	HPWMI_ODM	= 0x03,
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cienum hp_wmi_hardware_mask {
1008c2ecf20Sopenharmony_ci	HPWMI_DOCK_MASK		= 0x01,
1018c2ecf20Sopenharmony_ci	HPWMI_TABLET_MASK	= 0x04,
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistruct bios_return {
1058c2ecf20Sopenharmony_ci	u32 sigpass;
1068c2ecf20Sopenharmony_ci	u32 return_code;
1078c2ecf20Sopenharmony_ci};
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cienum hp_return_value {
1108c2ecf20Sopenharmony_ci	HPWMI_RET_WRONG_SIGNATURE	= 0x02,
1118c2ecf20Sopenharmony_ci	HPWMI_RET_UNKNOWN_COMMAND	= 0x03,
1128c2ecf20Sopenharmony_ci	HPWMI_RET_UNKNOWN_CMDTYPE	= 0x04,
1138c2ecf20Sopenharmony_ci	HPWMI_RET_INVALID_PARAMETERS	= 0x05,
1148c2ecf20Sopenharmony_ci};
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cienum hp_wireless2_bits {
1178c2ecf20Sopenharmony_ci	HPWMI_POWER_STATE	= 0x01,
1188c2ecf20Sopenharmony_ci	HPWMI_POWER_SOFT	= 0x02,
1198c2ecf20Sopenharmony_ci	HPWMI_POWER_BIOS	= 0x04,
1208c2ecf20Sopenharmony_ci	HPWMI_POWER_HARD	= 0x08,
1218c2ecf20Sopenharmony_ci	HPWMI_POWER_FW_OR_HW	= HPWMI_POWER_BIOS | HPWMI_POWER_HARD,
1228c2ecf20Sopenharmony_ci};
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci#define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW)
1258c2ecf20Sopenharmony_ci#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistruct bios_rfkill2_device_state {
1288c2ecf20Sopenharmony_ci	u8 radio_type;
1298c2ecf20Sopenharmony_ci	u8 bus_type;
1308c2ecf20Sopenharmony_ci	u16 vendor_id;
1318c2ecf20Sopenharmony_ci	u16 product_id;
1328c2ecf20Sopenharmony_ci	u16 subsys_vendor_id;
1338c2ecf20Sopenharmony_ci	u16 subsys_product_id;
1348c2ecf20Sopenharmony_ci	u8 rfkill_id;
1358c2ecf20Sopenharmony_ci	u8 power;
1368c2ecf20Sopenharmony_ci	u8 unknown[4];
1378c2ecf20Sopenharmony_ci};
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci/* 7 devices fit into the 128 byte buffer */
1408c2ecf20Sopenharmony_ci#define HPWMI_MAX_RFKILL2_DEVICES	7
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistruct bios_rfkill2_state {
1438c2ecf20Sopenharmony_ci	u8 unknown[7];
1448c2ecf20Sopenharmony_ci	u8 count;
1458c2ecf20Sopenharmony_ci	u8 pad[8];
1468c2ecf20Sopenharmony_ci	struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
1478c2ecf20Sopenharmony_ci};
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic const struct key_entry hp_wmi_keymap[] = {
1508c2ecf20Sopenharmony_ci	{ KE_KEY, 0x02,   { KEY_BRIGHTNESSUP } },
1518c2ecf20Sopenharmony_ci	{ KE_KEY, 0x03,   { KEY_BRIGHTNESSDOWN } },
1528c2ecf20Sopenharmony_ci	{ KE_KEY, 0x20e6, { KEY_PROG1 } },
1538c2ecf20Sopenharmony_ci	{ KE_KEY, 0x20e8, { KEY_MEDIA } },
1548c2ecf20Sopenharmony_ci	{ KE_KEY, 0x2142, { KEY_MEDIA } },
1558c2ecf20Sopenharmony_ci	{ KE_KEY, 0x213b, { KEY_INFO } },
1568c2ecf20Sopenharmony_ci	{ KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } },
1578c2ecf20Sopenharmony_ci	{ KE_KEY, 0x216a, { KEY_SETUP } },
1588c2ecf20Sopenharmony_ci	{ KE_KEY, 0x231b, { KEY_HELP } },
1598c2ecf20Sopenharmony_ci	{ KE_END, 0 }
1608c2ecf20Sopenharmony_ci};
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic struct input_dev *hp_wmi_input_dev;
1638c2ecf20Sopenharmony_cistatic struct platform_device *hp_wmi_platform_dev;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic struct rfkill *wifi_rfkill;
1668c2ecf20Sopenharmony_cistatic struct rfkill *bluetooth_rfkill;
1678c2ecf20Sopenharmony_cistatic struct rfkill *wwan_rfkill;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistruct rfkill2_device {
1708c2ecf20Sopenharmony_ci	u8 id;
1718c2ecf20Sopenharmony_ci	int num;
1728c2ecf20Sopenharmony_ci	struct rfkill *rfkill;
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic int rfkill2_count;
1768c2ecf20Sopenharmony_cistatic struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci/* map output size to the corresponding WMI method id */
1798c2ecf20Sopenharmony_cistatic inline int encode_outsize_for_pvsz(int outsize)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	if (outsize > 4096)
1828c2ecf20Sopenharmony_ci		return -EINVAL;
1838c2ecf20Sopenharmony_ci	if (outsize > 1024)
1848c2ecf20Sopenharmony_ci		return 5;
1858c2ecf20Sopenharmony_ci	if (outsize > 128)
1868c2ecf20Sopenharmony_ci		return 4;
1878c2ecf20Sopenharmony_ci	if (outsize > 4)
1888c2ecf20Sopenharmony_ci		return 3;
1898c2ecf20Sopenharmony_ci	if (outsize > 0)
1908c2ecf20Sopenharmony_ci		return 2;
1918c2ecf20Sopenharmony_ci	return 1;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci/*
1958c2ecf20Sopenharmony_ci * hp_wmi_perform_query
1968c2ecf20Sopenharmony_ci *
1978c2ecf20Sopenharmony_ci * query:	The commandtype (enum hp_wmi_commandtype)
1988c2ecf20Sopenharmony_ci * write:	The command (enum hp_wmi_command)
1998c2ecf20Sopenharmony_ci * buffer:	Buffer used as input and/or output
2008c2ecf20Sopenharmony_ci * insize:	Size of input buffer
2018c2ecf20Sopenharmony_ci * outsize:	Size of output buffer
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * returns zero on success
2048c2ecf20Sopenharmony_ci *         an HP WMI query specific error code (which is positive)
2058c2ecf20Sopenharmony_ci *         -EINVAL if the query was not successful at all
2068c2ecf20Sopenharmony_ci *         -EINVAL if the output buffer size exceeds buffersize
2078c2ecf20Sopenharmony_ci *
2088c2ecf20Sopenharmony_ci * Note: The buffersize must at least be the maximum of the input and output
2098c2ecf20Sopenharmony_ci *       size. E.g. Battery info query is defined to have 1 byte input
2108c2ecf20Sopenharmony_ci *       and 128 byte output. The caller would do:
2118c2ecf20Sopenharmony_ci *       buffer = kzalloc(128, GFP_KERNEL);
2128c2ecf20Sopenharmony_ci *       ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128)
2138c2ecf20Sopenharmony_ci */
2148c2ecf20Sopenharmony_cistatic int hp_wmi_perform_query(int query, enum hp_wmi_command command,
2158c2ecf20Sopenharmony_ci				void *buffer, int insize, int outsize)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	int mid;
2188c2ecf20Sopenharmony_ci	struct bios_return *bios_return;
2198c2ecf20Sopenharmony_ci	int actual_outsize;
2208c2ecf20Sopenharmony_ci	union acpi_object *obj;
2218c2ecf20Sopenharmony_ci	struct bios_args args = {
2228c2ecf20Sopenharmony_ci		.signature = 0x55434553,
2238c2ecf20Sopenharmony_ci		.command = command,
2248c2ecf20Sopenharmony_ci		.commandtype = query,
2258c2ecf20Sopenharmony_ci		.datasize = insize,
2268c2ecf20Sopenharmony_ci		.data = { 0 },
2278c2ecf20Sopenharmony_ci	};
2288c2ecf20Sopenharmony_ci	struct acpi_buffer input = { sizeof(struct bios_args), &args };
2298c2ecf20Sopenharmony_ci	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
2308c2ecf20Sopenharmony_ci	int ret = 0;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	mid = encode_outsize_for_pvsz(outsize);
2338c2ecf20Sopenharmony_ci	if (WARN_ON(mid < 0))
2348c2ecf20Sopenharmony_ci		return mid;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (WARN_ON(insize > sizeof(args.data)))
2378c2ecf20Sopenharmony_ci		return -EINVAL;
2388c2ecf20Sopenharmony_ci	memcpy(&args.data[0], buffer, insize);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	obj = output.pointer;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (!obj)
2458c2ecf20Sopenharmony_ci		return -EINVAL;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (obj->type != ACPI_TYPE_BUFFER) {
2488c2ecf20Sopenharmony_ci		ret = -EINVAL;
2498c2ecf20Sopenharmony_ci		goto out_free;
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	bios_return = (struct bios_return *)obj->buffer.pointer;
2538c2ecf20Sopenharmony_ci	ret = bios_return->return_code;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	if (ret) {
2568c2ecf20Sopenharmony_ci		if (ret != HPWMI_RET_UNKNOWN_COMMAND &&
2578c2ecf20Sopenharmony_ci		    ret != HPWMI_RET_UNKNOWN_CMDTYPE)
2588c2ecf20Sopenharmony_ci			pr_warn("query 0x%x returned error 0x%x\n", query, ret);
2598c2ecf20Sopenharmony_ci		goto out_free;
2608c2ecf20Sopenharmony_ci	}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/* Ignore output data of zero size */
2638c2ecf20Sopenharmony_ci	if (!outsize)
2648c2ecf20Sopenharmony_ci		goto out_free;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
2678c2ecf20Sopenharmony_ci	memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
2688c2ecf20Sopenharmony_ci	memset(buffer + actual_outsize, 0, outsize - actual_outsize);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ciout_free:
2718c2ecf20Sopenharmony_ci	kfree(obj);
2728c2ecf20Sopenharmony_ci	return ret;
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic int hp_wmi_read_int(int query)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	int val = 0, ret;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	ret = hp_wmi_perform_query(query, HPWMI_READ, &val,
2808c2ecf20Sopenharmony_ci				   sizeof(val), sizeof(val));
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	if (ret)
2838c2ecf20Sopenharmony_ci		return ret < 0 ? ret : -EINVAL;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	return val;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic int hp_wmi_hw_state(int mask)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (state < 0)
2938c2ecf20Sopenharmony_ci		return state;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	return !!(state & mask);
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic int __init hp_wmi_bios_2008_later(void)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	int state = 0;
3018c2ecf20Sopenharmony_ci	int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state,
3028c2ecf20Sopenharmony_ci				       sizeof(state), sizeof(state));
3038c2ecf20Sopenharmony_ci	if (!ret)
3048c2ecf20Sopenharmony_ci		return 1;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic int __init hp_wmi_bios_2009_later(void)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	u8 state[128];
3128c2ecf20Sopenharmony_ci	int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
3138c2ecf20Sopenharmony_ci				       sizeof(state), sizeof(state));
3148c2ecf20Sopenharmony_ci	if (!ret)
3158c2ecf20Sopenharmony_ci		return 1;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic int __init hp_wmi_enable_hotkeys(void)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	int value = 0x6e;
3238c2ecf20Sopenharmony_ci	int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value,
3248c2ecf20Sopenharmony_ci				       sizeof(value), 0);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return ret <= 0 ? ret : -EINVAL;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic int hp_wmi_set_block(void *data, bool blocked)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	enum hp_wmi_radio r = (enum hp_wmi_radio) data;
3328c2ecf20Sopenharmony_ci	int query = BIT(r + 8) | ((!blocked) << r);
3338c2ecf20Sopenharmony_ci	int ret;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE,
3368c2ecf20Sopenharmony_ci				   &query, sizeof(query), 0);
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	return ret <= 0 ? ret : -EINVAL;
3398c2ecf20Sopenharmony_ci}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_cistatic const struct rfkill_ops hp_wmi_rfkill_ops = {
3428c2ecf20Sopenharmony_ci	.set_block = hp_wmi_set_block,
3438c2ecf20Sopenharmony_ci};
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	int mask = 0x200 << (r * 8);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/* TBD: Pass error */
3528c2ecf20Sopenharmony_ci	WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	return !(wireless & mask);
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_cistatic bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
3588c2ecf20Sopenharmony_ci{
3598c2ecf20Sopenharmony_ci	int mask = 0x800 << (r * 8);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	/* TBD: Pass error */
3648c2ecf20Sopenharmony_ci	WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	return !(wireless & mask);
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic int hp_wmi_rfkill2_set_block(void *data, bool blocked)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	int rfkill_id = (int)(long)data;
3728c2ecf20Sopenharmony_ci	char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
3738c2ecf20Sopenharmony_ci	int ret;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE,
3768c2ecf20Sopenharmony_ci				   buffer, sizeof(buffer), 0);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	return ret <= 0 ? ret : -EINVAL;
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_cistatic const struct rfkill_ops hp_wmi_rfkill2_ops = {
3828c2ecf20Sopenharmony_ci	.set_block = hp_wmi_rfkill2_set_block,
3838c2ecf20Sopenharmony_ci};
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic int hp_wmi_rfkill2_refresh(void)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct bios_rfkill2_state state;
3888c2ecf20Sopenharmony_ci	int err, i;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
3918c2ecf20Sopenharmony_ci				   sizeof(state), sizeof(state));
3928c2ecf20Sopenharmony_ci	if (err)
3938c2ecf20Sopenharmony_ci		return err;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	for (i = 0; i < rfkill2_count; i++) {
3968c2ecf20Sopenharmony_ci		int num = rfkill2[i].num;
3978c2ecf20Sopenharmony_ci		struct bios_rfkill2_device_state *devstate;
3988c2ecf20Sopenharmony_ci		devstate = &state.device[num];
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci		if (num >= state.count ||
4018c2ecf20Sopenharmony_ci		    devstate->rfkill_id != rfkill2[i].id) {
4028c2ecf20Sopenharmony_ci			pr_warn("power configuration of the wireless devices unexpectedly changed\n");
4038c2ecf20Sopenharmony_ci			continue;
4048c2ecf20Sopenharmony_ci		}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci		rfkill_set_states(rfkill2[i].rfkill,
4078c2ecf20Sopenharmony_ci				  IS_SWBLOCKED(devstate->power),
4088c2ecf20Sopenharmony_ci				  IS_HWBLOCKED(devstate->power));
4098c2ecf20Sopenharmony_ci	}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	return 0;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic ssize_t display_show(struct device *dev, struct device_attribute *attr,
4158c2ecf20Sopenharmony_ci			    char *buf)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY);
4188c2ecf20Sopenharmony_ci	if (value < 0)
4198c2ecf20Sopenharmony_ci		return value;
4208c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", value);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cistatic ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr,
4248c2ecf20Sopenharmony_ci			    char *buf)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY);
4278c2ecf20Sopenharmony_ci	if (value < 0)
4288c2ecf20Sopenharmony_ci		return value;
4298c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", value);
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic ssize_t als_show(struct device *dev, struct device_attribute *attr,
4338c2ecf20Sopenharmony_ci			char *buf)
4348c2ecf20Sopenharmony_ci{
4358c2ecf20Sopenharmony_ci	int value = hp_wmi_read_int(HPWMI_ALS_QUERY);
4368c2ecf20Sopenharmony_ci	if (value < 0)
4378c2ecf20Sopenharmony_ci		return value;
4388c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", value);
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_cistatic ssize_t dock_show(struct device *dev, struct device_attribute *attr,
4428c2ecf20Sopenharmony_ci			 char *buf)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	int value = hp_wmi_hw_state(HPWMI_DOCK_MASK);
4458c2ecf20Sopenharmony_ci	if (value < 0)
4468c2ecf20Sopenharmony_ci		return value;
4478c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", value);
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_cistatic ssize_t tablet_show(struct device *dev, struct device_attribute *attr,
4518c2ecf20Sopenharmony_ci			   char *buf)
4528c2ecf20Sopenharmony_ci{
4538c2ecf20Sopenharmony_ci	int value = hp_wmi_hw_state(HPWMI_TABLET_MASK);
4548c2ecf20Sopenharmony_ci	if (value < 0)
4558c2ecf20Sopenharmony_ci		return value;
4568c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", value);
4578c2ecf20Sopenharmony_ci}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_cistatic ssize_t postcode_show(struct device *dev, struct device_attribute *attr,
4608c2ecf20Sopenharmony_ci			     char *buf)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	/* Get the POST error code of previous boot failure. */
4638c2ecf20Sopenharmony_ci	int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY);
4648c2ecf20Sopenharmony_ci	if (value < 0)
4658c2ecf20Sopenharmony_ci		return value;
4668c2ecf20Sopenharmony_ci	return sprintf(buf, "0x%x\n", value);
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_cistatic ssize_t als_store(struct device *dev, struct device_attribute *attr,
4708c2ecf20Sopenharmony_ci			 const char *buf, size_t count)
4718c2ecf20Sopenharmony_ci{
4728c2ecf20Sopenharmony_ci	u32 tmp;
4738c2ecf20Sopenharmony_ci	int ret;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	ret = kstrtou32(buf, 10, &tmp);
4768c2ecf20Sopenharmony_ci	if (ret)
4778c2ecf20Sopenharmony_ci		return ret;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
4808c2ecf20Sopenharmony_ci				       sizeof(tmp), sizeof(tmp));
4818c2ecf20Sopenharmony_ci	if (ret)
4828c2ecf20Sopenharmony_ci		return ret < 0 ? ret : -EINVAL;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	return count;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_cistatic ssize_t postcode_store(struct device *dev, struct device_attribute *attr,
4888c2ecf20Sopenharmony_ci			      const char *buf, size_t count)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	u32 tmp = 1;
4918c2ecf20Sopenharmony_ci	bool clear;
4928c2ecf20Sopenharmony_ci	int ret;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	ret = kstrtobool(buf, &clear);
4958c2ecf20Sopenharmony_ci	if (ret)
4968c2ecf20Sopenharmony_ci		return ret;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	if (clear == false)
4998c2ecf20Sopenharmony_ci		return -EINVAL;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	/* Clear the POST error code. It is kept until until cleared. */
5028c2ecf20Sopenharmony_ci	ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp,
5038c2ecf20Sopenharmony_ci				       sizeof(tmp), sizeof(tmp));
5048c2ecf20Sopenharmony_ci	if (ret)
5058c2ecf20Sopenharmony_ci		return ret < 0 ? ret : -EINVAL;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	return count;
5088c2ecf20Sopenharmony_ci}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(display);
5118c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(hddtemp);
5128c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(als);
5138c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(dock);
5148c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(tablet);
5158c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(postcode);
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic struct attribute *hp_wmi_attrs[] = {
5188c2ecf20Sopenharmony_ci	&dev_attr_display.attr,
5198c2ecf20Sopenharmony_ci	&dev_attr_hddtemp.attr,
5208c2ecf20Sopenharmony_ci	&dev_attr_als.attr,
5218c2ecf20Sopenharmony_ci	&dev_attr_dock.attr,
5228c2ecf20Sopenharmony_ci	&dev_attr_tablet.attr,
5238c2ecf20Sopenharmony_ci	&dev_attr_postcode.attr,
5248c2ecf20Sopenharmony_ci	NULL,
5258c2ecf20Sopenharmony_ci};
5268c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(hp_wmi);
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_cistatic void hp_wmi_notify(u32 value, void *context)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
5318c2ecf20Sopenharmony_ci	u32 event_id, event_data;
5328c2ecf20Sopenharmony_ci	union acpi_object *obj;
5338c2ecf20Sopenharmony_ci	acpi_status status;
5348c2ecf20Sopenharmony_ci	u32 *location;
5358c2ecf20Sopenharmony_ci	int key_code;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	status = wmi_get_event_data(value, &response);
5388c2ecf20Sopenharmony_ci	if (status != AE_OK) {
5398c2ecf20Sopenharmony_ci		pr_info("bad event status 0x%x\n", status);
5408c2ecf20Sopenharmony_ci		return;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	obj = (union acpi_object *)response.pointer;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	if (!obj)
5468c2ecf20Sopenharmony_ci		return;
5478c2ecf20Sopenharmony_ci	if (obj->type != ACPI_TYPE_BUFFER) {
5488c2ecf20Sopenharmony_ci		pr_info("Unknown response received %d\n", obj->type);
5498c2ecf20Sopenharmony_ci		kfree(obj);
5508c2ecf20Sopenharmony_ci		return;
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	/*
5548c2ecf20Sopenharmony_ci	 * Depending on ACPI version the concatenation of id and event data
5558c2ecf20Sopenharmony_ci	 * inside _WED function will result in a 8 or 16 byte buffer.
5568c2ecf20Sopenharmony_ci	 */
5578c2ecf20Sopenharmony_ci	location = (u32 *)obj->buffer.pointer;
5588c2ecf20Sopenharmony_ci	if (obj->buffer.length == 8) {
5598c2ecf20Sopenharmony_ci		event_id = *location;
5608c2ecf20Sopenharmony_ci		event_data = *(location + 1);
5618c2ecf20Sopenharmony_ci	} else if (obj->buffer.length == 16) {
5628c2ecf20Sopenharmony_ci		event_id = *location;
5638c2ecf20Sopenharmony_ci		event_data = *(location + 2);
5648c2ecf20Sopenharmony_ci	} else {
5658c2ecf20Sopenharmony_ci		pr_info("Unknown buffer length %d\n", obj->buffer.length);
5668c2ecf20Sopenharmony_ci		kfree(obj);
5678c2ecf20Sopenharmony_ci		return;
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci	kfree(obj);
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	switch (event_id) {
5728c2ecf20Sopenharmony_ci	case HPWMI_DOCK_EVENT:
5738c2ecf20Sopenharmony_ci		if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
5748c2ecf20Sopenharmony_ci			input_report_switch(hp_wmi_input_dev, SW_DOCK,
5758c2ecf20Sopenharmony_ci					    hp_wmi_hw_state(HPWMI_DOCK_MASK));
5768c2ecf20Sopenharmony_ci		if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
5778c2ecf20Sopenharmony_ci			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
5788c2ecf20Sopenharmony_ci					    hp_wmi_hw_state(HPWMI_TABLET_MASK));
5798c2ecf20Sopenharmony_ci		input_sync(hp_wmi_input_dev);
5808c2ecf20Sopenharmony_ci		break;
5818c2ecf20Sopenharmony_ci	case HPWMI_PARK_HDD:
5828c2ecf20Sopenharmony_ci		break;
5838c2ecf20Sopenharmony_ci	case HPWMI_SMART_ADAPTER:
5848c2ecf20Sopenharmony_ci		break;
5858c2ecf20Sopenharmony_ci	case HPWMI_BEZEL_BUTTON:
5868c2ecf20Sopenharmony_ci		key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
5878c2ecf20Sopenharmony_ci		if (key_code < 0)
5888c2ecf20Sopenharmony_ci			break;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci		if (!sparse_keymap_report_event(hp_wmi_input_dev,
5918c2ecf20Sopenharmony_ci						key_code, 1, true))
5928c2ecf20Sopenharmony_ci			pr_info("Unknown key code - 0x%x\n", key_code);
5938c2ecf20Sopenharmony_ci		break;
5948c2ecf20Sopenharmony_ci	case HPWMI_WIRELESS:
5958c2ecf20Sopenharmony_ci		if (rfkill2_count) {
5968c2ecf20Sopenharmony_ci			hp_wmi_rfkill2_refresh();
5978c2ecf20Sopenharmony_ci			break;
5988c2ecf20Sopenharmony_ci		}
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci		if (wifi_rfkill)
6018c2ecf20Sopenharmony_ci			rfkill_set_states(wifi_rfkill,
6028c2ecf20Sopenharmony_ci					  hp_wmi_get_sw_state(HPWMI_WIFI),
6038c2ecf20Sopenharmony_ci					  hp_wmi_get_hw_state(HPWMI_WIFI));
6048c2ecf20Sopenharmony_ci		if (bluetooth_rfkill)
6058c2ecf20Sopenharmony_ci			rfkill_set_states(bluetooth_rfkill,
6068c2ecf20Sopenharmony_ci					  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
6078c2ecf20Sopenharmony_ci					  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
6088c2ecf20Sopenharmony_ci		if (wwan_rfkill)
6098c2ecf20Sopenharmony_ci			rfkill_set_states(wwan_rfkill,
6108c2ecf20Sopenharmony_ci					  hp_wmi_get_sw_state(HPWMI_WWAN),
6118c2ecf20Sopenharmony_ci					  hp_wmi_get_hw_state(HPWMI_WWAN));
6128c2ecf20Sopenharmony_ci		break;
6138c2ecf20Sopenharmony_ci	case HPWMI_CPU_BATTERY_THROTTLE:
6148c2ecf20Sopenharmony_ci		pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
6158c2ecf20Sopenharmony_ci		break;
6168c2ecf20Sopenharmony_ci	case HPWMI_LOCK_SWITCH:
6178c2ecf20Sopenharmony_ci		break;
6188c2ecf20Sopenharmony_ci	case HPWMI_LID_SWITCH:
6198c2ecf20Sopenharmony_ci		break;
6208c2ecf20Sopenharmony_ci	case HPWMI_SCREEN_ROTATION:
6218c2ecf20Sopenharmony_ci		break;
6228c2ecf20Sopenharmony_ci	case HPWMI_COOLSENSE_SYSTEM_MOBILE:
6238c2ecf20Sopenharmony_ci		break;
6248c2ecf20Sopenharmony_ci	case HPWMI_COOLSENSE_SYSTEM_HOT:
6258c2ecf20Sopenharmony_ci		break;
6268c2ecf20Sopenharmony_ci	case HPWMI_PROXIMITY_SENSOR:
6278c2ecf20Sopenharmony_ci		break;
6288c2ecf20Sopenharmony_ci	case HPWMI_BACKLIT_KB_BRIGHTNESS:
6298c2ecf20Sopenharmony_ci		break;
6308c2ecf20Sopenharmony_ci	case HPWMI_PEAKSHIFT_PERIOD:
6318c2ecf20Sopenharmony_ci		break;
6328c2ecf20Sopenharmony_ci	case HPWMI_BATTERY_CHARGE_PERIOD:
6338c2ecf20Sopenharmony_ci		break;
6348c2ecf20Sopenharmony_ci	case HPWMI_SANITIZATION_MODE:
6358c2ecf20Sopenharmony_ci		break;
6368c2ecf20Sopenharmony_ci	case HPWMI_SMART_EXPERIENCE_APP:
6378c2ecf20Sopenharmony_ci		break;
6388c2ecf20Sopenharmony_ci	default:
6398c2ecf20Sopenharmony_ci		pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
6408c2ecf20Sopenharmony_ci		break;
6418c2ecf20Sopenharmony_ci	}
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_cistatic int __init hp_wmi_input_setup(void)
6458c2ecf20Sopenharmony_ci{
6468c2ecf20Sopenharmony_ci	acpi_status status;
6478c2ecf20Sopenharmony_ci	int err, val;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	hp_wmi_input_dev = input_allocate_device();
6508c2ecf20Sopenharmony_ci	if (!hp_wmi_input_dev)
6518c2ecf20Sopenharmony_ci		return -ENOMEM;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	hp_wmi_input_dev->name = "HP WMI hotkeys";
6548c2ecf20Sopenharmony_ci	hp_wmi_input_dev->phys = "wmi/input0";
6558c2ecf20Sopenharmony_ci	hp_wmi_input_dev->id.bustype = BUS_HOST;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	__set_bit(EV_SW, hp_wmi_input_dev->evbit);
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	/* Dock */
6608c2ecf20Sopenharmony_ci	val = hp_wmi_hw_state(HPWMI_DOCK_MASK);
6618c2ecf20Sopenharmony_ci	if (!(val < 0)) {
6628c2ecf20Sopenharmony_ci		__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
6638c2ecf20Sopenharmony_ci		input_report_switch(hp_wmi_input_dev, SW_DOCK, val);
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	/* Tablet mode */
6678c2ecf20Sopenharmony_ci	if (enable_tablet_mode_sw > 0) {
6688c2ecf20Sopenharmony_ci		val = hp_wmi_hw_state(HPWMI_TABLET_MASK);
6698c2ecf20Sopenharmony_ci		if (val >= 0) {
6708c2ecf20Sopenharmony_ci			__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
6718c2ecf20Sopenharmony_ci			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
6728c2ecf20Sopenharmony_ci		}
6738c2ecf20Sopenharmony_ci	}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
6768c2ecf20Sopenharmony_ci	if (err)
6778c2ecf20Sopenharmony_ci		goto err_free_dev;
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	/* Set initial hardware state */
6808c2ecf20Sopenharmony_ci	input_sync(hp_wmi_input_dev);
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later())
6838c2ecf20Sopenharmony_ci		hp_wmi_enable_hotkeys();
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
6868c2ecf20Sopenharmony_ci	if (ACPI_FAILURE(status)) {
6878c2ecf20Sopenharmony_ci		err = -EIO;
6888c2ecf20Sopenharmony_ci		goto err_free_dev;
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	err = input_register_device(hp_wmi_input_dev);
6928c2ecf20Sopenharmony_ci	if (err)
6938c2ecf20Sopenharmony_ci		goto err_uninstall_notifier;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	return 0;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci err_uninstall_notifier:
6988c2ecf20Sopenharmony_ci	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
6998c2ecf20Sopenharmony_ci err_free_dev:
7008c2ecf20Sopenharmony_ci	input_free_device(hp_wmi_input_dev);
7018c2ecf20Sopenharmony_ci	return err;
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_cistatic void hp_wmi_input_destroy(void)
7058c2ecf20Sopenharmony_ci{
7068c2ecf20Sopenharmony_ci	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
7078c2ecf20Sopenharmony_ci	input_unregister_device(hp_wmi_input_dev);
7088c2ecf20Sopenharmony_ci}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_cistatic int __init hp_wmi_rfkill_setup(struct platform_device *device)
7118c2ecf20Sopenharmony_ci{
7128c2ecf20Sopenharmony_ci	int err, wireless;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
7158c2ecf20Sopenharmony_ci	if (wireless < 0)
7168c2ecf20Sopenharmony_ci		return wireless;
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless,
7198c2ecf20Sopenharmony_ci				   sizeof(wireless), 0);
7208c2ecf20Sopenharmony_ci	if (err)
7218c2ecf20Sopenharmony_ci		return err;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	if (wireless & 0x1) {
7248c2ecf20Sopenharmony_ci		wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
7258c2ecf20Sopenharmony_ci					   RFKILL_TYPE_WLAN,
7268c2ecf20Sopenharmony_ci					   &hp_wmi_rfkill_ops,
7278c2ecf20Sopenharmony_ci					   (void *) HPWMI_WIFI);
7288c2ecf20Sopenharmony_ci		if (!wifi_rfkill)
7298c2ecf20Sopenharmony_ci			return -ENOMEM;
7308c2ecf20Sopenharmony_ci		rfkill_init_sw_state(wifi_rfkill,
7318c2ecf20Sopenharmony_ci				     hp_wmi_get_sw_state(HPWMI_WIFI));
7328c2ecf20Sopenharmony_ci		rfkill_set_hw_state(wifi_rfkill,
7338c2ecf20Sopenharmony_ci				    hp_wmi_get_hw_state(HPWMI_WIFI));
7348c2ecf20Sopenharmony_ci		err = rfkill_register(wifi_rfkill);
7358c2ecf20Sopenharmony_ci		if (err)
7368c2ecf20Sopenharmony_ci			goto register_wifi_error;
7378c2ecf20Sopenharmony_ci	}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	if (wireless & 0x2) {
7408c2ecf20Sopenharmony_ci		bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
7418c2ecf20Sopenharmony_ci						RFKILL_TYPE_BLUETOOTH,
7428c2ecf20Sopenharmony_ci						&hp_wmi_rfkill_ops,
7438c2ecf20Sopenharmony_ci						(void *) HPWMI_BLUETOOTH);
7448c2ecf20Sopenharmony_ci		if (!bluetooth_rfkill) {
7458c2ecf20Sopenharmony_ci			err = -ENOMEM;
7468c2ecf20Sopenharmony_ci			goto register_bluetooth_error;
7478c2ecf20Sopenharmony_ci		}
7488c2ecf20Sopenharmony_ci		rfkill_init_sw_state(bluetooth_rfkill,
7498c2ecf20Sopenharmony_ci				     hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
7508c2ecf20Sopenharmony_ci		rfkill_set_hw_state(bluetooth_rfkill,
7518c2ecf20Sopenharmony_ci				    hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
7528c2ecf20Sopenharmony_ci		err = rfkill_register(bluetooth_rfkill);
7538c2ecf20Sopenharmony_ci		if (err)
7548c2ecf20Sopenharmony_ci			goto register_bluetooth_error;
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	if (wireless & 0x4) {
7588c2ecf20Sopenharmony_ci		wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
7598c2ecf20Sopenharmony_ci					   RFKILL_TYPE_WWAN,
7608c2ecf20Sopenharmony_ci					   &hp_wmi_rfkill_ops,
7618c2ecf20Sopenharmony_ci					   (void *) HPWMI_WWAN);
7628c2ecf20Sopenharmony_ci		if (!wwan_rfkill) {
7638c2ecf20Sopenharmony_ci			err = -ENOMEM;
7648c2ecf20Sopenharmony_ci			goto register_wwan_error;
7658c2ecf20Sopenharmony_ci		}
7668c2ecf20Sopenharmony_ci		rfkill_init_sw_state(wwan_rfkill,
7678c2ecf20Sopenharmony_ci				     hp_wmi_get_sw_state(HPWMI_WWAN));
7688c2ecf20Sopenharmony_ci		rfkill_set_hw_state(wwan_rfkill,
7698c2ecf20Sopenharmony_ci				    hp_wmi_get_hw_state(HPWMI_WWAN));
7708c2ecf20Sopenharmony_ci		err = rfkill_register(wwan_rfkill);
7718c2ecf20Sopenharmony_ci		if (err)
7728c2ecf20Sopenharmony_ci			goto register_wwan_error;
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	return 0;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ciregister_wwan_error:
7788c2ecf20Sopenharmony_ci	rfkill_destroy(wwan_rfkill);
7798c2ecf20Sopenharmony_ci	wwan_rfkill = NULL;
7808c2ecf20Sopenharmony_ci	if (bluetooth_rfkill)
7818c2ecf20Sopenharmony_ci		rfkill_unregister(bluetooth_rfkill);
7828c2ecf20Sopenharmony_ciregister_bluetooth_error:
7838c2ecf20Sopenharmony_ci	rfkill_destroy(bluetooth_rfkill);
7848c2ecf20Sopenharmony_ci	bluetooth_rfkill = NULL;
7858c2ecf20Sopenharmony_ci	if (wifi_rfkill)
7868c2ecf20Sopenharmony_ci		rfkill_unregister(wifi_rfkill);
7878c2ecf20Sopenharmony_ciregister_wifi_error:
7888c2ecf20Sopenharmony_ci	rfkill_destroy(wifi_rfkill);
7898c2ecf20Sopenharmony_ci	wifi_rfkill = NULL;
7908c2ecf20Sopenharmony_ci	return err;
7918c2ecf20Sopenharmony_ci}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_cistatic int __init hp_wmi_rfkill2_setup(struct platform_device *device)
7948c2ecf20Sopenharmony_ci{
7958c2ecf20Sopenharmony_ci	struct bios_rfkill2_state state;
7968c2ecf20Sopenharmony_ci	int err, i;
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
7998c2ecf20Sopenharmony_ci				   sizeof(state), sizeof(state));
8008c2ecf20Sopenharmony_ci	if (err)
8018c2ecf20Sopenharmony_ci		return err < 0 ? err : -EINVAL;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
8048c2ecf20Sopenharmony_ci		pr_warn("unable to parse 0x1b query output\n");
8058c2ecf20Sopenharmony_ci		return -EINVAL;
8068c2ecf20Sopenharmony_ci	}
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	for (i = 0; i < state.count; i++) {
8098c2ecf20Sopenharmony_ci		struct rfkill *rfkill;
8108c2ecf20Sopenharmony_ci		enum rfkill_type type;
8118c2ecf20Sopenharmony_ci		char *name;
8128c2ecf20Sopenharmony_ci		switch (state.device[i].radio_type) {
8138c2ecf20Sopenharmony_ci		case HPWMI_WIFI:
8148c2ecf20Sopenharmony_ci			type = RFKILL_TYPE_WLAN;
8158c2ecf20Sopenharmony_ci			name = "hp-wifi";
8168c2ecf20Sopenharmony_ci			break;
8178c2ecf20Sopenharmony_ci		case HPWMI_BLUETOOTH:
8188c2ecf20Sopenharmony_ci			type = RFKILL_TYPE_BLUETOOTH;
8198c2ecf20Sopenharmony_ci			name = "hp-bluetooth";
8208c2ecf20Sopenharmony_ci			break;
8218c2ecf20Sopenharmony_ci		case HPWMI_WWAN:
8228c2ecf20Sopenharmony_ci			type = RFKILL_TYPE_WWAN;
8238c2ecf20Sopenharmony_ci			name = "hp-wwan";
8248c2ecf20Sopenharmony_ci			break;
8258c2ecf20Sopenharmony_ci		case HPWMI_GPS:
8268c2ecf20Sopenharmony_ci			type = RFKILL_TYPE_GPS;
8278c2ecf20Sopenharmony_ci			name = "hp-gps";
8288c2ecf20Sopenharmony_ci			break;
8298c2ecf20Sopenharmony_ci		default:
8308c2ecf20Sopenharmony_ci			pr_warn("unknown device type 0x%x\n",
8318c2ecf20Sopenharmony_ci				state.device[i].radio_type);
8328c2ecf20Sopenharmony_ci			continue;
8338c2ecf20Sopenharmony_ci		}
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci		if (!state.device[i].vendor_id) {
8368c2ecf20Sopenharmony_ci			pr_warn("zero device %d while %d reported\n",
8378c2ecf20Sopenharmony_ci				i, state.count);
8388c2ecf20Sopenharmony_ci			continue;
8398c2ecf20Sopenharmony_ci		}
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci		rfkill = rfkill_alloc(name, &device->dev, type,
8428c2ecf20Sopenharmony_ci				      &hp_wmi_rfkill2_ops, (void *)(long)i);
8438c2ecf20Sopenharmony_ci		if (!rfkill) {
8448c2ecf20Sopenharmony_ci			err = -ENOMEM;
8458c2ecf20Sopenharmony_ci			goto fail;
8468c2ecf20Sopenharmony_ci		}
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci		rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
8498c2ecf20Sopenharmony_ci		rfkill2[rfkill2_count].num = i;
8508c2ecf20Sopenharmony_ci		rfkill2[rfkill2_count].rfkill = rfkill;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci		rfkill_init_sw_state(rfkill,
8538c2ecf20Sopenharmony_ci				     IS_SWBLOCKED(state.device[i].power));
8548c2ecf20Sopenharmony_ci		rfkill_set_hw_state(rfkill,
8558c2ecf20Sopenharmony_ci				    IS_HWBLOCKED(state.device[i].power));
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci		if (!(state.device[i].power & HPWMI_POWER_BIOS))
8588c2ecf20Sopenharmony_ci			pr_info("device %s blocked by BIOS\n", name);
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci		err = rfkill_register(rfkill);
8618c2ecf20Sopenharmony_ci		if (err) {
8628c2ecf20Sopenharmony_ci			rfkill_destroy(rfkill);
8638c2ecf20Sopenharmony_ci			goto fail;
8648c2ecf20Sopenharmony_ci		}
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci		rfkill2_count++;
8678c2ecf20Sopenharmony_ci	}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	return 0;
8708c2ecf20Sopenharmony_cifail:
8718c2ecf20Sopenharmony_ci	for (; rfkill2_count > 0; rfkill2_count--) {
8728c2ecf20Sopenharmony_ci		rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
8738c2ecf20Sopenharmony_ci		rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
8748c2ecf20Sopenharmony_ci	}
8758c2ecf20Sopenharmony_ci	return err;
8768c2ecf20Sopenharmony_ci}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_cistatic int thermal_policy_setup(struct platform_device *device)
8798c2ecf20Sopenharmony_ci{
8808c2ecf20Sopenharmony_ci	int err, tp;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	tp = hp_wmi_read_int(HPWMI_THERMAL_POLICY_QUERY);
8838c2ecf20Sopenharmony_ci	if (tp < 0)
8848c2ecf20Sopenharmony_ci		return tp;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	/*
8878c2ecf20Sopenharmony_ci	 * call thermal policy write command to ensure that the firmware correctly
8888c2ecf20Sopenharmony_ci	 * sets the OEM variables for the DPTF
8898c2ecf20Sopenharmony_ci	 */
8908c2ecf20Sopenharmony_ci	err = hp_wmi_perform_query(HPWMI_THERMAL_POLICY_QUERY, HPWMI_WRITE, &tp,
8918c2ecf20Sopenharmony_ci							   sizeof(tp), 0);
8928c2ecf20Sopenharmony_ci	if (err)
8938c2ecf20Sopenharmony_ci		return err;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	return 0;
8968c2ecf20Sopenharmony_ci}
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_cistatic int __init hp_wmi_bios_setup(struct platform_device *device)
8998c2ecf20Sopenharmony_ci{
9008c2ecf20Sopenharmony_ci	/* clear detected rfkill devices */
9018c2ecf20Sopenharmony_ci	wifi_rfkill = NULL;
9028c2ecf20Sopenharmony_ci	bluetooth_rfkill = NULL;
9038c2ecf20Sopenharmony_ci	wwan_rfkill = NULL;
9048c2ecf20Sopenharmony_ci	rfkill2_count = 0;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	/*
9078c2ecf20Sopenharmony_ci	 * In pre-2009 BIOS, command 1Bh return 0x4 to indicate that
9088c2ecf20Sopenharmony_ci	 * BIOS no longer controls the power for the wireless
9098c2ecf20Sopenharmony_ci	 * devices. All features supported by this command will no
9108c2ecf20Sopenharmony_ci	 * longer be supported.
9118c2ecf20Sopenharmony_ci	 */
9128c2ecf20Sopenharmony_ci	if (!hp_wmi_bios_2009_later()) {
9138c2ecf20Sopenharmony_ci		if (hp_wmi_rfkill_setup(device))
9148c2ecf20Sopenharmony_ci			hp_wmi_rfkill2_setup(device);
9158c2ecf20Sopenharmony_ci	}
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	thermal_policy_setup(device);
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	return 0;
9208c2ecf20Sopenharmony_ci}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_cistatic int __exit hp_wmi_bios_remove(struct platform_device *device)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	int i;
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	for (i = 0; i < rfkill2_count; i++) {
9278c2ecf20Sopenharmony_ci		rfkill_unregister(rfkill2[i].rfkill);
9288c2ecf20Sopenharmony_ci		rfkill_destroy(rfkill2[i].rfkill);
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	if (wifi_rfkill) {
9328c2ecf20Sopenharmony_ci		rfkill_unregister(wifi_rfkill);
9338c2ecf20Sopenharmony_ci		rfkill_destroy(wifi_rfkill);
9348c2ecf20Sopenharmony_ci	}
9358c2ecf20Sopenharmony_ci	if (bluetooth_rfkill) {
9368c2ecf20Sopenharmony_ci		rfkill_unregister(bluetooth_rfkill);
9378c2ecf20Sopenharmony_ci		rfkill_destroy(bluetooth_rfkill);
9388c2ecf20Sopenharmony_ci	}
9398c2ecf20Sopenharmony_ci	if (wwan_rfkill) {
9408c2ecf20Sopenharmony_ci		rfkill_unregister(wwan_rfkill);
9418c2ecf20Sopenharmony_ci		rfkill_destroy(wwan_rfkill);
9428c2ecf20Sopenharmony_ci	}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	return 0;
9458c2ecf20Sopenharmony_ci}
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_cistatic int hp_wmi_resume_handler(struct device *device)
9488c2ecf20Sopenharmony_ci{
9498c2ecf20Sopenharmony_ci	/*
9508c2ecf20Sopenharmony_ci	 * Hardware state may have changed while suspended, so trigger
9518c2ecf20Sopenharmony_ci	 * input events for the current state. As this is a switch,
9528c2ecf20Sopenharmony_ci	 * the input layer will only actually pass it on if the state
9538c2ecf20Sopenharmony_ci	 * changed.
9548c2ecf20Sopenharmony_ci	 */
9558c2ecf20Sopenharmony_ci	if (hp_wmi_input_dev) {
9568c2ecf20Sopenharmony_ci		if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
9578c2ecf20Sopenharmony_ci			input_report_switch(hp_wmi_input_dev, SW_DOCK,
9588c2ecf20Sopenharmony_ci					    hp_wmi_hw_state(HPWMI_DOCK_MASK));
9598c2ecf20Sopenharmony_ci		if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
9608c2ecf20Sopenharmony_ci			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
9618c2ecf20Sopenharmony_ci					    hp_wmi_hw_state(HPWMI_TABLET_MASK));
9628c2ecf20Sopenharmony_ci		input_sync(hp_wmi_input_dev);
9638c2ecf20Sopenharmony_ci	}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci	if (rfkill2_count)
9668c2ecf20Sopenharmony_ci		hp_wmi_rfkill2_refresh();
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	if (wifi_rfkill)
9698c2ecf20Sopenharmony_ci		rfkill_set_states(wifi_rfkill,
9708c2ecf20Sopenharmony_ci				  hp_wmi_get_sw_state(HPWMI_WIFI),
9718c2ecf20Sopenharmony_ci				  hp_wmi_get_hw_state(HPWMI_WIFI));
9728c2ecf20Sopenharmony_ci	if (bluetooth_rfkill)
9738c2ecf20Sopenharmony_ci		rfkill_set_states(bluetooth_rfkill,
9748c2ecf20Sopenharmony_ci				  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
9758c2ecf20Sopenharmony_ci				  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
9768c2ecf20Sopenharmony_ci	if (wwan_rfkill)
9778c2ecf20Sopenharmony_ci		rfkill_set_states(wwan_rfkill,
9788c2ecf20Sopenharmony_ci				  hp_wmi_get_sw_state(HPWMI_WWAN),
9798c2ecf20Sopenharmony_ci				  hp_wmi_get_hw_state(HPWMI_WWAN));
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	return 0;
9828c2ecf20Sopenharmony_ci}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_cistatic const struct dev_pm_ops hp_wmi_pm_ops = {
9858c2ecf20Sopenharmony_ci	.resume  = hp_wmi_resume_handler,
9868c2ecf20Sopenharmony_ci	.restore  = hp_wmi_resume_handler,
9878c2ecf20Sopenharmony_ci};
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_cistatic struct platform_driver hp_wmi_driver = {
9908c2ecf20Sopenharmony_ci	.driver = {
9918c2ecf20Sopenharmony_ci		.name = "hp-wmi",
9928c2ecf20Sopenharmony_ci		.pm = &hp_wmi_pm_ops,
9938c2ecf20Sopenharmony_ci		.dev_groups = hp_wmi_groups,
9948c2ecf20Sopenharmony_ci	},
9958c2ecf20Sopenharmony_ci	.remove = __exit_p(hp_wmi_bios_remove),
9968c2ecf20Sopenharmony_ci};
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_cistatic int __init hp_wmi_init(void)
9998c2ecf20Sopenharmony_ci{
10008c2ecf20Sopenharmony_ci	int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
10018c2ecf20Sopenharmony_ci	int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
10028c2ecf20Sopenharmony_ci	int err;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	if (!bios_capable && !event_capable)
10058c2ecf20Sopenharmony_ci		return -ENODEV;
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	if (event_capable) {
10088c2ecf20Sopenharmony_ci		err = hp_wmi_input_setup();
10098c2ecf20Sopenharmony_ci		if (err)
10108c2ecf20Sopenharmony_ci			return err;
10118c2ecf20Sopenharmony_ci	}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	if (bios_capable) {
10148c2ecf20Sopenharmony_ci		hp_wmi_platform_dev =
10158c2ecf20Sopenharmony_ci			platform_device_register_simple("hp-wmi", -1, NULL, 0);
10168c2ecf20Sopenharmony_ci		if (IS_ERR(hp_wmi_platform_dev)) {
10178c2ecf20Sopenharmony_ci			err = PTR_ERR(hp_wmi_platform_dev);
10188c2ecf20Sopenharmony_ci			goto err_destroy_input;
10198c2ecf20Sopenharmony_ci		}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci		err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup);
10228c2ecf20Sopenharmony_ci		if (err)
10238c2ecf20Sopenharmony_ci			goto err_unregister_device;
10248c2ecf20Sopenharmony_ci	}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	return 0;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_cierr_unregister_device:
10298c2ecf20Sopenharmony_ci	platform_device_unregister(hp_wmi_platform_dev);
10308c2ecf20Sopenharmony_cierr_destroy_input:
10318c2ecf20Sopenharmony_ci	if (event_capable)
10328c2ecf20Sopenharmony_ci		hp_wmi_input_destroy();
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	return err;
10358c2ecf20Sopenharmony_ci}
10368c2ecf20Sopenharmony_cimodule_init(hp_wmi_init);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_cistatic void __exit hp_wmi_exit(void)
10398c2ecf20Sopenharmony_ci{
10408c2ecf20Sopenharmony_ci	if (wmi_has_guid(HPWMI_EVENT_GUID))
10418c2ecf20Sopenharmony_ci		hp_wmi_input_destroy();
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (hp_wmi_platform_dev) {
10448c2ecf20Sopenharmony_ci		platform_device_unregister(hp_wmi_platform_dev);
10458c2ecf20Sopenharmony_ci		platform_driver_unregister(&hp_wmi_driver);
10468c2ecf20Sopenharmony_ci	}
10478c2ecf20Sopenharmony_ci}
10488c2ecf20Sopenharmony_cimodule_exit(hp_wmi_exit);
1049