Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * HP WMI hotkeys
0004  *
0005  * Copyright (C) 2008 Red Hat <mjg@redhat.com>
0006  * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
0007  *
0008  * Portions based on wistron_btns.c:
0009  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
0010  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
0011  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
0012  */
0013 
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015 
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/init.h>
0019 #include <linux/slab.h>
0020 #include <linux/types.h>
0021 #include <linux/input.h>
0022 #include <linux/input/sparse-keymap.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/platform_profile.h>
0025 #include <linux/hwmon.h>
0026 #include <linux/acpi.h>
0027 #include <linux/rfkill.h>
0028 #include <linux/string.h>
0029 #include <linux/dmi.h>
0030 
0031 MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>");
0032 MODULE_DESCRIPTION("HP laptop WMI hotkeys driver");
0033 MODULE_LICENSE("GPL");
0034 
0035 MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
0036 MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
0037 
0038 #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
0039 #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
0040 #define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95
0041 #define zero_if_sup(tmp) (zero_insize_support?0:sizeof(tmp)) // use when zero insize is required
0042 
0043 /* DMI board names of devices that should use the omen specific path for
0044  * thermal profiles.
0045  * This was obtained by taking a look in the windows omen command center
0046  * app and parsing a json file that they use to figure out what capabilities
0047  * the device should have.
0048  * A device is considered an omen if the DisplayName in that list contains
0049  * "OMEN", and it can use the thermal profile stuff if the "Feature" array
0050  * contains "PerformanceControl".
0051  */
0052 static const char * const omen_thermal_profile_boards[] = {
0053     "84DA", "84DB", "84DC", "8574", "8575", "860A", "87B5", "8572", "8573",
0054     "8600", "8601", "8602", "8605", "8606", "8607", "8746", "8747", "8749",
0055     "874A", "8603", "8604", "8748", "886B", "886C", "878A", "878B", "878C",
0056     "88C8", "88CB", "8786", "8787", "8788", "88D1", "88D2", "88F4", "88FD",
0057     "88F5", "88F6", "88F7", "88FE", "88FF", "8900", "8901", "8902", "8912",
0058     "8917", "8918", "8949", "894A", "89EB"
0059 };
0060 
0061 /* DMI Board names of Omen laptops that are specifically set to be thermal
0062  * profile version 0 by the Omen Command Center app, regardless of what
0063  * the get system design information WMI call returns
0064  */
0065 static const char *const omen_thermal_profile_force_v0_boards[] = {
0066     "8607", "8746", "8747", "8749", "874A", "8748"
0067 };
0068 
0069 enum hp_wmi_radio {
0070     HPWMI_WIFI  = 0x0,
0071     HPWMI_BLUETOOTH = 0x1,
0072     HPWMI_WWAN  = 0x2,
0073     HPWMI_GPS   = 0x3,
0074 };
0075 
0076 enum hp_wmi_event_ids {
0077     HPWMI_DOCK_EVENT        = 0x01,
0078     HPWMI_PARK_HDD          = 0x02,
0079     HPWMI_SMART_ADAPTER     = 0x03,
0080     HPWMI_BEZEL_BUTTON      = 0x04,
0081     HPWMI_WIRELESS          = 0x05,
0082     HPWMI_CPU_BATTERY_THROTTLE  = 0x06,
0083     HPWMI_LOCK_SWITCH       = 0x07,
0084     HPWMI_LID_SWITCH        = 0x08,
0085     HPWMI_SCREEN_ROTATION       = 0x09,
0086     HPWMI_COOLSENSE_SYSTEM_MOBILE   = 0x0A,
0087     HPWMI_COOLSENSE_SYSTEM_HOT  = 0x0B,
0088     HPWMI_PROXIMITY_SENSOR      = 0x0C,
0089     HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D,
0090     HPWMI_PEAKSHIFT_PERIOD      = 0x0F,
0091     HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
0092     HPWMI_SANITIZATION_MODE     = 0x17,
0093 };
0094 
0095 /*
0096  * struct bios_args buffer is dynamically allocated.  New WMI command types
0097  * were introduced that exceeds 128-byte data size.  Changes to handle
0098  * the data size allocation scheme were kept in hp_wmi_perform_qurey function.
0099  */
0100 struct bios_args {
0101     u32 signature;
0102     u32 command;
0103     u32 commandtype;
0104     u32 datasize;
0105     u8 data[];
0106 };
0107 
0108 enum hp_wmi_commandtype {
0109     HPWMI_DISPLAY_QUERY     = 0x01,
0110     HPWMI_HDDTEMP_QUERY     = 0x02,
0111     HPWMI_ALS_QUERY         = 0x03,
0112     HPWMI_HARDWARE_QUERY        = 0x04,
0113     HPWMI_WIRELESS_QUERY        = 0x05,
0114     HPWMI_BATTERY_QUERY     = 0x07,
0115     HPWMI_BIOS_QUERY        = 0x09,
0116     HPWMI_FEATURE_QUERY     = 0x0b,
0117     HPWMI_HOTKEY_QUERY      = 0x0c,
0118     HPWMI_FEATURE2_QUERY        = 0x0d,
0119     HPWMI_WIRELESS2_QUERY       = 0x1b,
0120     HPWMI_POSTCODEERROR_QUERY   = 0x2a,
0121     HPWMI_SYSTEM_DEVICE_MODE    = 0x40,
0122     HPWMI_THERMAL_PROFILE_QUERY = 0x4c,
0123 };
0124 
0125 enum hp_wmi_gm_commandtype {
0126     HPWMI_FAN_SPEED_GET_QUERY = 0x11,
0127     HPWMI_SET_PERFORMANCE_MODE = 0x1A,
0128     HPWMI_FAN_SPEED_MAX_GET_QUERY = 0x26,
0129     HPWMI_FAN_SPEED_MAX_SET_QUERY = 0x27,
0130     HPWMI_GET_SYSTEM_DESIGN_DATA = 0x28,
0131 };
0132 
0133 enum hp_wmi_command {
0134     HPWMI_READ  = 0x01,
0135     HPWMI_WRITE = 0x02,
0136     HPWMI_ODM   = 0x03,
0137     HPWMI_GM    = 0x20008,
0138 };
0139 
0140 enum hp_wmi_hardware_mask {
0141     HPWMI_DOCK_MASK     = 0x01,
0142     HPWMI_TABLET_MASK   = 0x04,
0143 };
0144 
0145 struct bios_return {
0146     u32 sigpass;
0147     u32 return_code;
0148 };
0149 
0150 enum hp_return_value {
0151     HPWMI_RET_WRONG_SIGNATURE   = 0x02,
0152     HPWMI_RET_UNKNOWN_COMMAND   = 0x03,
0153     HPWMI_RET_UNKNOWN_CMDTYPE   = 0x04,
0154     HPWMI_RET_INVALID_PARAMETERS    = 0x05,
0155 };
0156 
0157 enum hp_wireless2_bits {
0158     HPWMI_POWER_STATE   = 0x01,
0159     HPWMI_POWER_SOFT    = 0x02,
0160     HPWMI_POWER_BIOS    = 0x04,
0161     HPWMI_POWER_HARD    = 0x08,
0162     HPWMI_POWER_FW_OR_HW    = HPWMI_POWER_BIOS | HPWMI_POWER_HARD,
0163 };
0164 
0165 enum hp_thermal_profile_omen_v0 {
0166     HP_OMEN_V0_THERMAL_PROFILE_DEFAULT     = 0x00,
0167     HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE = 0x01,
0168     HP_OMEN_V0_THERMAL_PROFILE_COOL        = 0x02,
0169 };
0170 
0171 enum hp_thermal_profile_omen_v1 {
0172     HP_OMEN_V1_THERMAL_PROFILE_DEFAULT  = 0x30,
0173     HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE  = 0x31,
0174     HP_OMEN_V1_THERMAL_PROFILE_COOL     = 0x50,
0175 };
0176 
0177 enum hp_thermal_profile {
0178     HP_THERMAL_PROFILE_PERFORMANCE  = 0x00,
0179     HP_THERMAL_PROFILE_DEFAULT      = 0x01,
0180     HP_THERMAL_PROFILE_COOL         = 0x02
0181 };
0182 
0183 #define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW)
0184 #define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
0185 
0186 struct bios_rfkill2_device_state {
0187     u8 radio_type;
0188     u8 bus_type;
0189     u16 vendor_id;
0190     u16 product_id;
0191     u16 subsys_vendor_id;
0192     u16 subsys_product_id;
0193     u8 rfkill_id;
0194     u8 power;
0195     u8 unknown[4];
0196 };
0197 
0198 /* 7 devices fit into the 128 byte buffer */
0199 #define HPWMI_MAX_RFKILL2_DEVICES   7
0200 
0201 struct bios_rfkill2_state {
0202     u8 unknown[7];
0203     u8 count;
0204     u8 pad[8];
0205     struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
0206 };
0207 
0208 static const struct key_entry hp_wmi_keymap[] = {
0209     { KE_KEY, 0x02,   { KEY_BRIGHTNESSUP } },
0210     { KE_KEY, 0x03,   { KEY_BRIGHTNESSDOWN } },
0211     { KE_KEY, 0x20e6, { KEY_PROG1 } },
0212     { KE_KEY, 0x20e8, { KEY_MEDIA } },
0213     { KE_KEY, 0x2142, { KEY_MEDIA } },
0214     { KE_KEY, 0x213b, { KEY_INFO } },
0215     { KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } },
0216     { KE_KEY, 0x216a, { KEY_SETUP } },
0217     { KE_KEY, 0x231b, { KEY_HELP } },
0218     { KE_END, 0 }
0219 };
0220 
0221 static struct input_dev *hp_wmi_input_dev;
0222 static struct platform_device *hp_wmi_platform_dev;
0223 static struct platform_profile_handler platform_profile_handler;
0224 static bool platform_profile_support;
0225 static bool zero_insize_support;
0226 
0227 static struct rfkill *wifi_rfkill;
0228 static struct rfkill *bluetooth_rfkill;
0229 static struct rfkill *wwan_rfkill;
0230 
0231 struct rfkill2_device {
0232     u8 id;
0233     int num;
0234     struct rfkill *rfkill;
0235 };
0236 
0237 static int rfkill2_count;
0238 static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
0239 
0240 /*
0241  * Chassis Types values were obtained from SMBIOS reference
0242  * specification version 3.00. A complete list of system enclosures
0243  * and chassis types is available on Table 17.
0244  */
0245 static const char * const tablet_chassis_types[] = {
0246     "30", /* Tablet*/
0247     "31", /* Convertible */
0248     "32"  /* Detachable */
0249 };
0250 
0251 #define DEVICE_MODE_TABLET  0x06
0252 
0253 /* map output size to the corresponding WMI method id */
0254 static inline int encode_outsize_for_pvsz(int outsize)
0255 {
0256     if (outsize > 4096)
0257         return -EINVAL;
0258     if (outsize > 1024)
0259         return 5;
0260     if (outsize > 128)
0261         return 4;
0262     if (outsize > 4)
0263         return 3;
0264     if (outsize > 0)
0265         return 2;
0266     return 1;
0267 }
0268 
0269 /*
0270  * hp_wmi_perform_query
0271  *
0272  * query:   The commandtype (enum hp_wmi_commandtype)
0273  * write:   The command (enum hp_wmi_command)
0274  * buffer:  Buffer used as input and/or output
0275  * insize:  Size of input buffer
0276  * outsize: Size of output buffer
0277  *
0278  * returns zero on success
0279  *         an HP WMI query specific error code (which is positive)
0280  *         -EINVAL if the query was not successful at all
0281  *         -EINVAL if the output buffer size exceeds buffersize
0282  *
0283  * Note: The buffersize must at least be the maximum of the input and output
0284  *       size. E.g. Battery info query is defined to have 1 byte input
0285  *       and 128 byte output. The caller would do:
0286  *       buffer = kzalloc(128, GFP_KERNEL);
0287  *       ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128)
0288  */
0289 static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
0290                 void *buffer, int insize, int outsize)
0291 {
0292     struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL };
0293     struct bios_return *bios_return;
0294     union acpi_object *obj = NULL;
0295     struct bios_args *args = NULL;
0296     int mid, actual_insize, actual_outsize;
0297     size_t bios_args_size;
0298     int ret;
0299 
0300     mid = encode_outsize_for_pvsz(outsize);
0301     if (WARN_ON(mid < 0))
0302         return mid;
0303 
0304     actual_insize = max(insize, 128);
0305     bios_args_size = struct_size(args, data, actual_insize);
0306     args = kmalloc(bios_args_size, GFP_KERNEL);
0307     if (!args)
0308         return -ENOMEM;
0309 
0310     input.length = bios_args_size;
0311     input.pointer = args;
0312 
0313     args->signature = 0x55434553;
0314     args->command = command;
0315     args->commandtype = query;
0316     args->datasize = insize;
0317     memcpy(args->data, buffer, flex_array_size(args, data, insize));
0318 
0319     ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
0320     if (ret)
0321         goto out_free;
0322 
0323     obj = output.pointer;
0324     if (!obj) {
0325         ret = -EINVAL;
0326         goto out_free;
0327     }
0328 
0329     if (obj->type != ACPI_TYPE_BUFFER) {
0330         pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret);
0331         ret = -EINVAL;
0332         goto out_free;
0333     }
0334 
0335     bios_return = (struct bios_return *)obj->buffer.pointer;
0336     ret = bios_return->return_code;
0337 
0338     if (ret) {
0339         if (ret != HPWMI_RET_UNKNOWN_COMMAND &&
0340             ret != HPWMI_RET_UNKNOWN_CMDTYPE)
0341             pr_warn("query 0x%x returned error 0x%x\n", query, ret);
0342         goto out_free;
0343     }
0344 
0345     /* Ignore output data of zero size */
0346     if (!outsize)
0347         goto out_free;
0348 
0349     actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
0350     memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
0351     memset(buffer + actual_outsize, 0, outsize - actual_outsize);
0352 
0353 out_free:
0354     kfree(obj);
0355     kfree(args);
0356     return ret;
0357 }
0358 
0359 static int hp_wmi_get_fan_speed(int fan)
0360 {
0361     u8 fsh, fsl;
0362     char fan_data[4] = { fan, 0, 0, 0 };
0363 
0364     int ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_GET_QUERY, HPWMI_GM,
0365                        &fan_data, sizeof(char),
0366                        sizeof(fan_data));
0367 
0368     if (ret != 0)
0369         return -EINVAL;
0370 
0371     fsh = fan_data[2];
0372     fsl = fan_data[3];
0373 
0374     return (fsh << 8) | fsl;
0375 }
0376 
0377 static int hp_wmi_read_int(int query)
0378 {
0379     int val = 0, ret;
0380 
0381     ret = hp_wmi_perform_query(query, HPWMI_READ, &val,
0382                    zero_if_sup(val), sizeof(val));
0383 
0384     if (ret)
0385         return ret < 0 ? ret : -EINVAL;
0386 
0387     return val;
0388 }
0389 
0390 static int hp_wmi_get_dock_state(void)
0391 {
0392     int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY);
0393 
0394     if (state < 0)
0395         return state;
0396 
0397     return !!(state & HPWMI_DOCK_MASK);
0398 }
0399 
0400 static int hp_wmi_get_tablet_mode(void)
0401 {
0402     char system_device_mode[4] = { 0 };
0403     const char *chassis_type;
0404     bool tablet_found;
0405     int ret;
0406 
0407     chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
0408     if (!chassis_type)
0409         return -ENODEV;
0410 
0411     tablet_found = match_string(tablet_chassis_types,
0412                     ARRAY_SIZE(tablet_chassis_types),
0413                     chassis_type) >= 0;
0414     if (!tablet_found)
0415         return -ENODEV;
0416 
0417     ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ,
0418                    system_device_mode, zero_if_sup(system_device_mode),
0419                    sizeof(system_device_mode));
0420     if (ret < 0)
0421         return ret;
0422 
0423     return system_device_mode[0] == DEVICE_MODE_TABLET;
0424 }
0425 
0426 static int omen_thermal_profile_set(int mode)
0427 {
0428     char buffer[2] = {0, mode};
0429     int ret;
0430 
0431     ret = hp_wmi_perform_query(HPWMI_SET_PERFORMANCE_MODE, HPWMI_GM,
0432                    &buffer, sizeof(buffer), 0);
0433 
0434     if (ret)
0435         return ret < 0 ? ret : -EINVAL;
0436 
0437     return mode;
0438 }
0439 
0440 static bool is_omen_thermal_profile(void)
0441 {
0442     const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
0443 
0444     if (!board_name)
0445         return false;
0446 
0447     return match_string(omen_thermal_profile_boards,
0448                 ARRAY_SIZE(omen_thermal_profile_boards),
0449                 board_name) >= 0;
0450 }
0451 
0452 static int omen_get_thermal_policy_version(void)
0453 {
0454     unsigned char buffer[8] = { 0 };
0455     int ret;
0456 
0457     const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
0458 
0459     if (board_name) {
0460         int matches = match_string(omen_thermal_profile_force_v0_boards,
0461             ARRAY_SIZE(omen_thermal_profile_force_v0_boards),
0462             board_name);
0463         if (matches >= 0)
0464             return 0;
0465     }
0466 
0467     ret = hp_wmi_perform_query(HPWMI_GET_SYSTEM_DESIGN_DATA, HPWMI_GM,
0468                    &buffer, sizeof(buffer), sizeof(buffer));
0469 
0470     if (ret)
0471         return ret < 0 ? ret : -EINVAL;
0472 
0473     return buffer[3];
0474 }
0475 
0476 static int omen_thermal_profile_get(void)
0477 {
0478     u8 data;
0479 
0480     int ret = ec_read(HP_OMEN_EC_THERMAL_PROFILE_OFFSET, &data);
0481 
0482     if (ret)
0483         return ret;
0484 
0485     return data;
0486 }
0487 
0488 static int hp_wmi_fan_speed_max_set(int enabled)
0489 {
0490     int ret;
0491 
0492     ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_SET_QUERY, HPWMI_GM,
0493                    &enabled, sizeof(enabled), 0);
0494 
0495     if (ret)
0496         return ret < 0 ? ret : -EINVAL;
0497 
0498     return enabled;
0499 }
0500 
0501 static int hp_wmi_fan_speed_max_get(void)
0502 {
0503     int val = 0, ret;
0504 
0505     ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_GET_QUERY, HPWMI_GM,
0506                    &val, zero_if_sup(val), sizeof(val));
0507 
0508     if (ret)
0509         return ret < 0 ? ret : -EINVAL;
0510 
0511     return val;
0512 }
0513 
0514 static int __init hp_wmi_bios_2008_later(void)
0515 {
0516     int state = 0;
0517     int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state,
0518                        zero_if_sup(state), sizeof(state));
0519     if (!ret)
0520         return 1;
0521 
0522     return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
0523 }
0524 
0525 static int __init hp_wmi_bios_2009_later(void)
0526 {
0527     u8 state[128];
0528     int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
0529                        zero_if_sup(state), sizeof(state));
0530     if (!ret)
0531         return 1;
0532 
0533     return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
0534 }
0535 
0536 static int __init hp_wmi_enable_hotkeys(void)
0537 {
0538     int value = 0x6e;
0539     int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value,
0540                        sizeof(value), 0);
0541 
0542     return ret <= 0 ? ret : -EINVAL;
0543 }
0544 
0545 static int hp_wmi_set_block(void *data, bool blocked)
0546 {
0547     enum hp_wmi_radio r = (enum hp_wmi_radio) data;
0548     int query = BIT(r + 8) | ((!blocked) << r);
0549     int ret;
0550 
0551     ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE,
0552                    &query, sizeof(query), 0);
0553 
0554     return ret <= 0 ? ret : -EINVAL;
0555 }
0556 
0557 static const struct rfkill_ops hp_wmi_rfkill_ops = {
0558     .set_block = hp_wmi_set_block,
0559 };
0560 
0561 static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
0562 {
0563     int mask = 0x200 << (r * 8);
0564 
0565     int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
0566 
0567     /* TBD: Pass error */
0568     WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
0569 
0570     return !(wireless & mask);
0571 }
0572 
0573 static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
0574 {
0575     int mask = 0x800 << (r * 8);
0576 
0577     int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
0578 
0579     /* TBD: Pass error */
0580     WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
0581 
0582     return !(wireless & mask);
0583 }
0584 
0585 static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
0586 {
0587     int rfkill_id = (int)(long)data;
0588     char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
0589     int ret;
0590 
0591     ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE,
0592                    buffer, sizeof(buffer), 0);
0593 
0594     return ret <= 0 ? ret : -EINVAL;
0595 }
0596 
0597 static const struct rfkill_ops hp_wmi_rfkill2_ops = {
0598     .set_block = hp_wmi_rfkill2_set_block,
0599 };
0600 
0601 static int hp_wmi_rfkill2_refresh(void)
0602 {
0603     struct bios_rfkill2_state state;
0604     int err, i;
0605 
0606     err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
0607                    zero_if_sup(state), sizeof(state));
0608     if (err)
0609         return err;
0610 
0611     for (i = 0; i < rfkill2_count; i++) {
0612         int num = rfkill2[i].num;
0613         struct bios_rfkill2_device_state *devstate;
0614 
0615         devstate = &state.device[num];
0616 
0617         if (num >= state.count ||
0618             devstate->rfkill_id != rfkill2[i].id) {
0619             pr_warn("power configuration of the wireless devices unexpectedly changed\n");
0620             continue;
0621         }
0622 
0623         rfkill_set_states(rfkill2[i].rfkill,
0624                   IS_SWBLOCKED(devstate->power),
0625                   IS_HWBLOCKED(devstate->power));
0626     }
0627 
0628     return 0;
0629 }
0630 
0631 static ssize_t display_show(struct device *dev, struct device_attribute *attr,
0632                 char *buf)
0633 {
0634     int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY);
0635 
0636     if (value < 0)
0637         return value;
0638     return sprintf(buf, "%d\n", value);
0639 }
0640 
0641 static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr,
0642                 char *buf)
0643 {
0644     int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY);
0645 
0646     if (value < 0)
0647         return value;
0648     return sprintf(buf, "%d\n", value);
0649 }
0650 
0651 static ssize_t als_show(struct device *dev, struct device_attribute *attr,
0652             char *buf)
0653 {
0654     int value = hp_wmi_read_int(HPWMI_ALS_QUERY);
0655 
0656     if (value < 0)
0657         return value;
0658     return sprintf(buf, "%d\n", value);
0659 }
0660 
0661 static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
0662              char *buf)
0663 {
0664     int value = hp_wmi_get_dock_state();
0665 
0666     if (value < 0)
0667         return value;
0668     return sprintf(buf, "%d\n", value);
0669 }
0670 
0671 static ssize_t tablet_show(struct device *dev, struct device_attribute *attr,
0672                char *buf)
0673 {
0674     int value = hp_wmi_get_tablet_mode();
0675 
0676     if (value < 0)
0677         return value;
0678     return sprintf(buf, "%d\n", value);
0679 }
0680 
0681 static ssize_t postcode_show(struct device *dev, struct device_attribute *attr,
0682                  char *buf)
0683 {
0684     /* Get the POST error code of previous boot failure. */
0685     int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY);
0686 
0687     if (value < 0)
0688         return value;
0689     return sprintf(buf, "0x%x\n", value);
0690 }
0691 
0692 static ssize_t als_store(struct device *dev, struct device_attribute *attr,
0693              const char *buf, size_t count)
0694 {
0695     u32 tmp;
0696     int ret;
0697 
0698     ret = kstrtou32(buf, 10, &tmp);
0699     if (ret)
0700         return ret;
0701 
0702     ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
0703                        sizeof(tmp), 0);
0704     if (ret)
0705         return ret < 0 ? ret : -EINVAL;
0706 
0707     return count;
0708 }
0709 
0710 static ssize_t postcode_store(struct device *dev, struct device_attribute *attr,
0711                   const char *buf, size_t count)
0712 {
0713     u32 tmp = 1;
0714     bool clear;
0715     int ret;
0716 
0717     ret = kstrtobool(buf, &clear);
0718     if (ret)
0719         return ret;
0720 
0721     if (clear == false)
0722         return -EINVAL;
0723 
0724     /* Clear the POST error code. It is kept until cleared. */
0725     ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp,
0726                        sizeof(tmp), 0);
0727     if (ret)
0728         return ret < 0 ? ret : -EINVAL;
0729 
0730     return count;
0731 }
0732 
0733 static DEVICE_ATTR_RO(display);
0734 static DEVICE_ATTR_RO(hddtemp);
0735 static DEVICE_ATTR_RW(als);
0736 static DEVICE_ATTR_RO(dock);
0737 static DEVICE_ATTR_RO(tablet);
0738 static DEVICE_ATTR_RW(postcode);
0739 
0740 static struct attribute *hp_wmi_attrs[] = {
0741     &dev_attr_display.attr,
0742     &dev_attr_hddtemp.attr,
0743     &dev_attr_als.attr,
0744     &dev_attr_dock.attr,
0745     &dev_attr_tablet.attr,
0746     &dev_attr_postcode.attr,
0747     NULL,
0748 };
0749 ATTRIBUTE_GROUPS(hp_wmi);
0750 
0751 static void hp_wmi_notify(u32 value, void *context)
0752 {
0753     struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
0754     u32 event_id, event_data;
0755     union acpi_object *obj;
0756     acpi_status status;
0757     u32 *location;
0758     int key_code;
0759 
0760     status = wmi_get_event_data(value, &response);
0761     if (status != AE_OK) {
0762         pr_info("bad event status 0x%x\n", status);
0763         return;
0764     }
0765 
0766     obj = (union acpi_object *)response.pointer;
0767 
0768     if (!obj)
0769         return;
0770     if (obj->type != ACPI_TYPE_BUFFER) {
0771         pr_info("Unknown response received %d\n", obj->type);
0772         kfree(obj);
0773         return;
0774     }
0775 
0776     /*
0777      * Depending on ACPI version the concatenation of id and event data
0778      * inside _WED function will result in a 8 or 16 byte buffer.
0779      */
0780     location = (u32 *)obj->buffer.pointer;
0781     if (obj->buffer.length == 8) {
0782         event_id = *location;
0783         event_data = *(location + 1);
0784     } else if (obj->buffer.length == 16) {
0785         event_id = *location;
0786         event_data = *(location + 2);
0787     } else {
0788         pr_info("Unknown buffer length %d\n", obj->buffer.length);
0789         kfree(obj);
0790         return;
0791     }
0792     kfree(obj);
0793 
0794     switch (event_id) {
0795     case HPWMI_DOCK_EVENT:
0796         if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
0797             input_report_switch(hp_wmi_input_dev, SW_DOCK,
0798                         hp_wmi_get_dock_state());
0799         if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
0800             input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
0801                         hp_wmi_get_tablet_mode());
0802         input_sync(hp_wmi_input_dev);
0803         break;
0804     case HPWMI_PARK_HDD:
0805         break;
0806     case HPWMI_SMART_ADAPTER:
0807         break;
0808     case HPWMI_BEZEL_BUTTON:
0809         key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
0810         if (key_code < 0)
0811             break;
0812 
0813         if (!sparse_keymap_report_event(hp_wmi_input_dev,
0814                         key_code, 1, true))
0815             pr_info("Unknown key code - 0x%x\n", key_code);
0816         break;
0817     case HPWMI_WIRELESS:
0818         if (rfkill2_count) {
0819             hp_wmi_rfkill2_refresh();
0820             break;
0821         }
0822 
0823         if (wifi_rfkill)
0824             rfkill_set_states(wifi_rfkill,
0825                       hp_wmi_get_sw_state(HPWMI_WIFI),
0826                       hp_wmi_get_hw_state(HPWMI_WIFI));
0827         if (bluetooth_rfkill)
0828             rfkill_set_states(bluetooth_rfkill,
0829                       hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
0830                       hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
0831         if (wwan_rfkill)
0832             rfkill_set_states(wwan_rfkill,
0833                       hp_wmi_get_sw_state(HPWMI_WWAN),
0834                       hp_wmi_get_hw_state(HPWMI_WWAN));
0835         break;
0836     case HPWMI_CPU_BATTERY_THROTTLE:
0837         pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
0838         break;
0839     case HPWMI_LOCK_SWITCH:
0840         break;
0841     case HPWMI_LID_SWITCH:
0842         break;
0843     case HPWMI_SCREEN_ROTATION:
0844         break;
0845     case HPWMI_COOLSENSE_SYSTEM_MOBILE:
0846         break;
0847     case HPWMI_COOLSENSE_SYSTEM_HOT:
0848         break;
0849     case HPWMI_PROXIMITY_SENSOR:
0850         break;
0851     case HPWMI_BACKLIT_KB_BRIGHTNESS:
0852         break;
0853     case HPWMI_PEAKSHIFT_PERIOD:
0854         break;
0855     case HPWMI_BATTERY_CHARGE_PERIOD:
0856         break;
0857     case HPWMI_SANITIZATION_MODE:
0858         break;
0859     default:
0860         pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
0861         break;
0862     }
0863 }
0864 
0865 static int __init hp_wmi_input_setup(void)
0866 {
0867     acpi_status status;
0868     int err, val;
0869 
0870     hp_wmi_input_dev = input_allocate_device();
0871     if (!hp_wmi_input_dev)
0872         return -ENOMEM;
0873 
0874     hp_wmi_input_dev->name = "HP WMI hotkeys";
0875     hp_wmi_input_dev->phys = "wmi/input0";
0876     hp_wmi_input_dev->id.bustype = BUS_HOST;
0877 
0878     __set_bit(EV_SW, hp_wmi_input_dev->evbit);
0879 
0880     /* Dock */
0881     val = hp_wmi_get_dock_state();
0882     if (!(val < 0)) {
0883         __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
0884         input_report_switch(hp_wmi_input_dev, SW_DOCK, val);
0885     }
0886 
0887     /* Tablet mode */
0888     val = hp_wmi_get_tablet_mode();
0889     if (!(val < 0)) {
0890         __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
0891         input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
0892     }
0893 
0894     err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
0895     if (err)
0896         goto err_free_dev;
0897 
0898     /* Set initial hardware state */
0899     input_sync(hp_wmi_input_dev);
0900 
0901     if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later())
0902         hp_wmi_enable_hotkeys();
0903 
0904     status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
0905     if (ACPI_FAILURE(status)) {
0906         err = -EIO;
0907         goto err_free_dev;
0908     }
0909 
0910     err = input_register_device(hp_wmi_input_dev);
0911     if (err)
0912         goto err_uninstall_notifier;
0913 
0914     return 0;
0915 
0916  err_uninstall_notifier:
0917     wmi_remove_notify_handler(HPWMI_EVENT_GUID);
0918  err_free_dev:
0919     input_free_device(hp_wmi_input_dev);
0920     return err;
0921 }
0922 
0923 static void hp_wmi_input_destroy(void)
0924 {
0925     wmi_remove_notify_handler(HPWMI_EVENT_GUID);
0926     input_unregister_device(hp_wmi_input_dev);
0927 }
0928 
0929 static int __init hp_wmi_rfkill_setup(struct platform_device *device)
0930 {
0931     int err, wireless;
0932 
0933     wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
0934     if (wireless < 0)
0935         return wireless;
0936 
0937     err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless,
0938                    sizeof(wireless), 0);
0939     if (err)
0940         return err;
0941 
0942     if (wireless & 0x1) {
0943         wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
0944                        RFKILL_TYPE_WLAN,
0945                        &hp_wmi_rfkill_ops,
0946                        (void *) HPWMI_WIFI);
0947         if (!wifi_rfkill)
0948             return -ENOMEM;
0949         rfkill_init_sw_state(wifi_rfkill,
0950                      hp_wmi_get_sw_state(HPWMI_WIFI));
0951         rfkill_set_hw_state(wifi_rfkill,
0952                     hp_wmi_get_hw_state(HPWMI_WIFI));
0953         err = rfkill_register(wifi_rfkill);
0954         if (err)
0955             goto register_wifi_error;
0956     }
0957 
0958     if (wireless & 0x2) {
0959         bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
0960                         RFKILL_TYPE_BLUETOOTH,
0961                         &hp_wmi_rfkill_ops,
0962                         (void *) HPWMI_BLUETOOTH);
0963         if (!bluetooth_rfkill) {
0964             err = -ENOMEM;
0965             goto register_bluetooth_error;
0966         }
0967         rfkill_init_sw_state(bluetooth_rfkill,
0968                      hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
0969         rfkill_set_hw_state(bluetooth_rfkill,
0970                     hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
0971         err = rfkill_register(bluetooth_rfkill);
0972         if (err)
0973             goto register_bluetooth_error;
0974     }
0975 
0976     if (wireless & 0x4) {
0977         wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
0978                        RFKILL_TYPE_WWAN,
0979                        &hp_wmi_rfkill_ops,
0980                        (void *) HPWMI_WWAN);
0981         if (!wwan_rfkill) {
0982             err = -ENOMEM;
0983             goto register_wwan_error;
0984         }
0985         rfkill_init_sw_state(wwan_rfkill,
0986                      hp_wmi_get_sw_state(HPWMI_WWAN));
0987         rfkill_set_hw_state(wwan_rfkill,
0988                     hp_wmi_get_hw_state(HPWMI_WWAN));
0989         err = rfkill_register(wwan_rfkill);
0990         if (err)
0991             goto register_wwan_error;
0992     }
0993 
0994     return 0;
0995 
0996 register_wwan_error:
0997     rfkill_destroy(wwan_rfkill);
0998     wwan_rfkill = NULL;
0999     if (bluetooth_rfkill)
1000         rfkill_unregister(bluetooth_rfkill);
1001 register_bluetooth_error:
1002     rfkill_destroy(bluetooth_rfkill);
1003     bluetooth_rfkill = NULL;
1004     if (wifi_rfkill)
1005         rfkill_unregister(wifi_rfkill);
1006 register_wifi_error:
1007     rfkill_destroy(wifi_rfkill);
1008     wifi_rfkill = NULL;
1009     return err;
1010 }
1011 
1012 static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
1013 {
1014     struct bios_rfkill2_state state;
1015     int err, i;
1016 
1017     err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
1018                    zero_if_sup(state), sizeof(state));
1019     if (err)
1020         return err < 0 ? err : -EINVAL;
1021 
1022     if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
1023         pr_warn("unable to parse 0x1b query output\n");
1024         return -EINVAL;
1025     }
1026 
1027     for (i = 0; i < state.count; i++) {
1028         struct rfkill *rfkill;
1029         enum rfkill_type type;
1030         char *name;
1031 
1032         switch (state.device[i].radio_type) {
1033         case HPWMI_WIFI:
1034             type = RFKILL_TYPE_WLAN;
1035             name = "hp-wifi";
1036             break;
1037         case HPWMI_BLUETOOTH:
1038             type = RFKILL_TYPE_BLUETOOTH;
1039             name = "hp-bluetooth";
1040             break;
1041         case HPWMI_WWAN:
1042             type = RFKILL_TYPE_WWAN;
1043             name = "hp-wwan";
1044             break;
1045         case HPWMI_GPS:
1046             type = RFKILL_TYPE_GPS;
1047             name = "hp-gps";
1048             break;
1049         default:
1050             pr_warn("unknown device type 0x%x\n",
1051                 state.device[i].radio_type);
1052             continue;
1053         }
1054 
1055         if (!state.device[i].vendor_id) {
1056             pr_warn("zero device %d while %d reported\n",
1057                 i, state.count);
1058             continue;
1059         }
1060 
1061         rfkill = rfkill_alloc(name, &device->dev, type,
1062                       &hp_wmi_rfkill2_ops, (void *)(long)i);
1063         if (!rfkill) {
1064             err = -ENOMEM;
1065             goto fail;
1066         }
1067 
1068         rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
1069         rfkill2[rfkill2_count].num = i;
1070         rfkill2[rfkill2_count].rfkill = rfkill;
1071 
1072         rfkill_init_sw_state(rfkill,
1073                      IS_SWBLOCKED(state.device[i].power));
1074         rfkill_set_hw_state(rfkill,
1075                     IS_HWBLOCKED(state.device[i].power));
1076 
1077         if (!(state.device[i].power & HPWMI_POWER_BIOS))
1078             pr_info("device %s blocked by BIOS\n", name);
1079 
1080         err = rfkill_register(rfkill);
1081         if (err) {
1082             rfkill_destroy(rfkill);
1083             goto fail;
1084         }
1085 
1086         rfkill2_count++;
1087     }
1088 
1089     return 0;
1090 fail:
1091     for (; rfkill2_count > 0; rfkill2_count--) {
1092         rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
1093         rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
1094     }
1095     return err;
1096 }
1097 
1098 static int platform_profile_omen_get(struct platform_profile_handler *pprof,
1099                      enum platform_profile_option *profile)
1100 {
1101     int tp;
1102 
1103     tp = omen_thermal_profile_get();
1104     if (tp < 0)
1105         return tp;
1106 
1107     switch (tp) {
1108     case HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE:
1109     case HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE:
1110         *profile = PLATFORM_PROFILE_PERFORMANCE;
1111         break;
1112     case HP_OMEN_V0_THERMAL_PROFILE_DEFAULT:
1113     case HP_OMEN_V1_THERMAL_PROFILE_DEFAULT:
1114         *profile = PLATFORM_PROFILE_BALANCED;
1115         break;
1116     case HP_OMEN_V0_THERMAL_PROFILE_COOL:
1117     case HP_OMEN_V1_THERMAL_PROFILE_COOL:
1118         *profile = PLATFORM_PROFILE_COOL;
1119         break;
1120     default:
1121         return -EINVAL;
1122     }
1123 
1124     return 0;
1125 }
1126 
1127 static int platform_profile_omen_set(struct platform_profile_handler *pprof,
1128                      enum platform_profile_option profile)
1129 {
1130     int err, tp, tp_version;
1131 
1132     tp_version = omen_get_thermal_policy_version();
1133 
1134     if (tp_version < 0 || tp_version > 1)
1135         return -EOPNOTSUPP;
1136 
1137     switch (profile) {
1138     case PLATFORM_PROFILE_PERFORMANCE:
1139         if (tp_version == 0)
1140             tp = HP_OMEN_V0_THERMAL_PROFILE_PERFORMANCE;
1141         else
1142             tp = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE;
1143         break;
1144     case PLATFORM_PROFILE_BALANCED:
1145         if (tp_version == 0)
1146             tp = HP_OMEN_V0_THERMAL_PROFILE_DEFAULT;
1147         else
1148             tp = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT;
1149         break;
1150     case PLATFORM_PROFILE_COOL:
1151         if (tp_version == 0)
1152             tp = HP_OMEN_V0_THERMAL_PROFILE_COOL;
1153         else
1154             tp = HP_OMEN_V1_THERMAL_PROFILE_COOL;
1155         break;
1156     default:
1157         return -EOPNOTSUPP;
1158     }
1159 
1160     err = omen_thermal_profile_set(tp);
1161     if (err < 0)
1162         return err;
1163 
1164     return 0;
1165 }
1166 
1167 static int thermal_profile_get(void)
1168 {
1169     return hp_wmi_read_int(HPWMI_THERMAL_PROFILE_QUERY);
1170 }
1171 
1172 static int thermal_profile_set(int thermal_profile)
1173 {
1174     return hp_wmi_perform_query(HPWMI_THERMAL_PROFILE_QUERY, HPWMI_WRITE, &thermal_profile,
1175                                sizeof(thermal_profile), 0);
1176 }
1177 
1178 static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof,
1179                     enum platform_profile_option *profile)
1180 {
1181     int tp;
1182 
1183     tp = thermal_profile_get();
1184     if (tp < 0)
1185         return tp;
1186 
1187     switch (tp) {
1188     case HP_THERMAL_PROFILE_PERFORMANCE:
1189         *profile =  PLATFORM_PROFILE_PERFORMANCE;
1190         break;
1191     case HP_THERMAL_PROFILE_DEFAULT:
1192         *profile =  PLATFORM_PROFILE_BALANCED;
1193         break;
1194     case HP_THERMAL_PROFILE_COOL:
1195         *profile =  PLATFORM_PROFILE_COOL;
1196         break;
1197     default:
1198         return -EINVAL;
1199     }
1200 
1201     return 0;
1202 }
1203 
1204 static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof,
1205                     enum platform_profile_option profile)
1206 {
1207     int err, tp;
1208 
1209     switch (profile) {
1210     case PLATFORM_PROFILE_PERFORMANCE:
1211         tp =  HP_THERMAL_PROFILE_PERFORMANCE;
1212         break;
1213     case PLATFORM_PROFILE_BALANCED:
1214         tp =  HP_THERMAL_PROFILE_DEFAULT;
1215         break;
1216     case PLATFORM_PROFILE_COOL:
1217         tp =  HP_THERMAL_PROFILE_COOL;
1218         break;
1219     default:
1220         return -EOPNOTSUPP;
1221     }
1222 
1223     err = thermal_profile_set(tp);
1224     if (err)
1225         return err;
1226 
1227     return 0;
1228 }
1229 
1230 static int thermal_profile_setup(void)
1231 {
1232     int err, tp;
1233 
1234     if (is_omen_thermal_profile()) {
1235         tp = omen_thermal_profile_get();
1236         if (tp < 0)
1237             return tp;
1238 
1239         /*
1240          * call thermal profile write command to ensure that the
1241          * firmware correctly sets the OEM variables
1242          */
1243 
1244         err = omen_thermal_profile_set(tp);
1245         if (err < 0)
1246             return err;
1247 
1248         platform_profile_handler.profile_get = platform_profile_omen_get;
1249         platform_profile_handler.profile_set = platform_profile_omen_set;
1250     } else {
1251         tp = thermal_profile_get();
1252 
1253         if (tp < 0)
1254             return tp;
1255 
1256         /*
1257          * call thermal profile write command to ensure that the
1258          * firmware correctly sets the OEM variables for the DPTF
1259          */
1260         err = thermal_profile_set(tp);
1261         if (err)
1262             return err;
1263 
1264         platform_profile_handler.profile_get = hp_wmi_platform_profile_get;
1265         platform_profile_handler.profile_set = hp_wmi_platform_profile_set;
1266     }
1267 
1268     set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
1269     set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
1270     set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
1271 
1272     err = platform_profile_register(&platform_profile_handler);
1273     if (err)
1274         return err;
1275 
1276     platform_profile_support = true;
1277 
1278     return 0;
1279 }
1280 
1281 static int hp_wmi_hwmon_init(void);
1282 
1283 static int __init hp_wmi_bios_setup(struct platform_device *device)
1284 {
1285     int err;
1286     /* clear detected rfkill devices */
1287     wifi_rfkill = NULL;
1288     bluetooth_rfkill = NULL;
1289     wwan_rfkill = NULL;
1290     rfkill2_count = 0;
1291 
1292     if (hp_wmi_rfkill_setup(device))
1293         hp_wmi_rfkill2_setup(device);
1294 
1295     err = hp_wmi_hwmon_init();
1296 
1297     if (err < 0)
1298         return err;
1299 
1300     thermal_profile_setup();
1301 
1302     return 0;
1303 }
1304 
1305 static int __exit hp_wmi_bios_remove(struct platform_device *device)
1306 {
1307     int i;
1308 
1309     for (i = 0; i < rfkill2_count; i++) {
1310         rfkill_unregister(rfkill2[i].rfkill);
1311         rfkill_destroy(rfkill2[i].rfkill);
1312     }
1313 
1314     if (wifi_rfkill) {
1315         rfkill_unregister(wifi_rfkill);
1316         rfkill_destroy(wifi_rfkill);
1317     }
1318     if (bluetooth_rfkill) {
1319         rfkill_unregister(bluetooth_rfkill);
1320         rfkill_destroy(bluetooth_rfkill);
1321     }
1322     if (wwan_rfkill) {
1323         rfkill_unregister(wwan_rfkill);
1324         rfkill_destroy(wwan_rfkill);
1325     }
1326 
1327     if (platform_profile_support)
1328         platform_profile_remove();
1329 
1330     return 0;
1331 }
1332 
1333 static int hp_wmi_resume_handler(struct device *device)
1334 {
1335     /*
1336      * Hardware state may have changed while suspended, so trigger
1337      * input events for the current state. As this is a switch,
1338      * the input layer will only actually pass it on if the state
1339      * changed.
1340      */
1341     if (hp_wmi_input_dev) {
1342         if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
1343             input_report_switch(hp_wmi_input_dev, SW_DOCK,
1344                         hp_wmi_get_dock_state());
1345         if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
1346             input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
1347                         hp_wmi_get_tablet_mode());
1348         input_sync(hp_wmi_input_dev);
1349     }
1350 
1351     if (rfkill2_count)
1352         hp_wmi_rfkill2_refresh();
1353 
1354     if (wifi_rfkill)
1355         rfkill_set_states(wifi_rfkill,
1356                   hp_wmi_get_sw_state(HPWMI_WIFI),
1357                   hp_wmi_get_hw_state(HPWMI_WIFI));
1358     if (bluetooth_rfkill)
1359         rfkill_set_states(bluetooth_rfkill,
1360                   hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
1361                   hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
1362     if (wwan_rfkill)
1363         rfkill_set_states(wwan_rfkill,
1364                   hp_wmi_get_sw_state(HPWMI_WWAN),
1365                   hp_wmi_get_hw_state(HPWMI_WWAN));
1366 
1367     return 0;
1368 }
1369 
1370 static const struct dev_pm_ops hp_wmi_pm_ops = {
1371     .resume  = hp_wmi_resume_handler,
1372     .restore  = hp_wmi_resume_handler,
1373 };
1374 
1375 static struct platform_driver hp_wmi_driver = {
1376     .driver = {
1377         .name = "hp-wmi",
1378         .pm = &hp_wmi_pm_ops,
1379         .dev_groups = hp_wmi_groups,
1380     },
1381     .remove = __exit_p(hp_wmi_bios_remove),
1382 };
1383 
1384 static umode_t hp_wmi_hwmon_is_visible(const void *data,
1385                        enum hwmon_sensor_types type,
1386                        u32 attr, int channel)
1387 {
1388     switch (type) {
1389     case hwmon_pwm:
1390         return 0644;
1391     case hwmon_fan:
1392         if (hp_wmi_get_fan_speed(channel) >= 0)
1393             return 0444;
1394         break;
1395     default:
1396         return 0;
1397     }
1398 
1399     return 0;
1400 }
1401 
1402 static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
1403                  u32 attr, int channel, long *val)
1404 {
1405     int ret;
1406 
1407     switch (type) {
1408     case hwmon_fan:
1409         ret = hp_wmi_get_fan_speed(channel);
1410 
1411         if (ret < 0)
1412             return ret;
1413         *val = ret;
1414         return 0;
1415     case hwmon_pwm:
1416         switch (hp_wmi_fan_speed_max_get()) {
1417         case 0:
1418             /* 0 is automatic fan, which is 2 for hwmon */
1419             *val = 2;
1420             return 0;
1421         case 1:
1422             /* 1 is max fan, which is 0
1423              * (no fan speed control) for hwmon
1424              */
1425             *val = 0;
1426             return 0;
1427         default:
1428             /* shouldn't happen */
1429             return -ENODATA;
1430         }
1431     default:
1432         return -EINVAL;
1433     }
1434 }
1435 
1436 static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
1437                   u32 attr, int channel, long val)
1438 {
1439     switch (type) {
1440     case hwmon_pwm:
1441         switch (val) {
1442         case 0:
1443             /* 0 is no fan speed control (max), which is 1 for us */
1444             return hp_wmi_fan_speed_max_set(1);
1445         case 2:
1446             /* 2 is automatic speed control, which is 0 for us */
1447             return hp_wmi_fan_speed_max_set(0);
1448         default:
1449             /* we don't support manual fan speed control */
1450             return -EINVAL;
1451         }
1452     default:
1453         return -EOPNOTSUPP;
1454     }
1455 }
1456 
1457 static const struct hwmon_channel_info *info[] = {
1458     HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT),
1459     HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE),
1460     NULL
1461 };
1462 
1463 static const struct hwmon_ops ops = {
1464     .is_visible = hp_wmi_hwmon_is_visible,
1465     .read = hp_wmi_hwmon_read,
1466     .write = hp_wmi_hwmon_write,
1467 };
1468 
1469 static const struct hwmon_chip_info chip_info = {
1470     .ops = &ops,
1471     .info = info,
1472 };
1473 
1474 static int hp_wmi_hwmon_init(void)
1475 {
1476     struct device *dev = &hp_wmi_platform_dev->dev;
1477     struct device *hwmon;
1478 
1479     hwmon = devm_hwmon_device_register_with_info(dev, "hp", &hp_wmi_driver,
1480                              &chip_info, NULL);
1481 
1482     if (IS_ERR(hwmon)) {
1483         dev_err(dev, "Could not register hp hwmon device\n");
1484         return PTR_ERR(hwmon);
1485     }
1486 
1487     return 0;
1488 }
1489 
1490 static int __init hp_wmi_init(void)
1491 {
1492     int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
1493     int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
1494     int err, tmp = 0;
1495 
1496     if (!bios_capable && !event_capable)
1497         return -ENODEV;
1498 
1499     if (hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, HPWMI_READ, &tmp,
1500                  sizeof(tmp), sizeof(tmp)) == HPWMI_RET_INVALID_PARAMETERS)
1501         zero_insize_support = true;
1502 
1503     if (event_capable) {
1504         err = hp_wmi_input_setup();
1505         if (err)
1506             return err;
1507     }
1508 
1509     if (bios_capable) {
1510         hp_wmi_platform_dev =
1511             platform_device_register_simple("hp-wmi", -1, NULL, 0);
1512         if (IS_ERR(hp_wmi_platform_dev)) {
1513             err = PTR_ERR(hp_wmi_platform_dev);
1514             goto err_destroy_input;
1515         }
1516 
1517         err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup);
1518         if (err)
1519             goto err_unregister_device;
1520     }
1521 
1522     return 0;
1523 
1524 err_unregister_device:
1525     platform_device_unregister(hp_wmi_platform_dev);
1526 err_destroy_input:
1527     if (event_capable)
1528         hp_wmi_input_destroy();
1529 
1530     return err;
1531 }
1532 module_init(hp_wmi_init);
1533 
1534 static void __exit hp_wmi_exit(void)
1535 {
1536     if (wmi_has_guid(HPWMI_EVENT_GUID))
1537         hp_wmi_input_destroy();
1538 
1539     if (hp_wmi_platform_dev) {
1540         platform_device_unregister(hp_wmi_platform_dev);
1541         platform_driver_unregister(&hp_wmi_driver);
1542     }
1543 }
1544 module_exit(hp_wmi_exit);