0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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))
0042
0043
0044
0045
0046
0047
0048
0049
0050
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
0062
0063
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
0097
0098
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
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
0242
0243
0244
0245 static const char * const tablet_chassis_types[] = {
0246 "30",
0247 "31",
0248 "32"
0249 };
0250
0251 #define DEVICE_MODE_TABLET 0x06
0252
0253
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
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
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
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
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
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
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
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
0778
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
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
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
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
1241
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
1258
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
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
1337
1338
1339
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
1419 *val = 2;
1420 return 0;
1421 case 1:
1422
1423
1424
1425 *val = 0;
1426 return 0;
1427 default:
1428
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
1444 return hp_wmi_fan_speed_max_set(1);
1445 case 2:
1446
1447 return hp_wmi_fan_speed_max_set(0);
1448 default:
1449
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);