.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * HP WMI hotkeys |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> |
---|
9 | 10 | * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> |
---|
10 | 11 | * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify |
---|
13 | | - * it under the terms of the GNU General Public License as published by |
---|
14 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
15 | | - * (at your option) any later version. |
---|
16 | | - * |
---|
17 | | - * This program is distributed in the hope that it will be useful, |
---|
18 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
19 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
20 | | - * GNU General Public License for more details. |
---|
21 | | - * |
---|
22 | | - * You should have received a copy of the GNU General Public License |
---|
23 | | - * along with this program; if not, write to the Free Software |
---|
24 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
25 | 12 | */ |
---|
26 | 13 | |
---|
27 | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
75 | 62 | HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D, |
---|
76 | 63 | HPWMI_PEAKSHIFT_PERIOD = 0x0F, |
---|
77 | 64 | HPWMI_BATTERY_CHARGE_PERIOD = 0x10, |
---|
| 65 | + HPWMI_SANITIZATION_MODE = 0x17, |
---|
| 66 | + HPWMI_SMART_EXPERIENCE_APP = 0x21, |
---|
78 | 67 | }; |
---|
79 | 68 | |
---|
80 | 69 | struct bios_args { |
---|
.. | .. |
---|
98 | 87 | HPWMI_FEATURE2_QUERY = 0x0d, |
---|
99 | 88 | HPWMI_WIRELESS2_QUERY = 0x1b, |
---|
100 | 89 | HPWMI_POSTCODEERROR_QUERY = 0x2a, |
---|
| 90 | + HPWMI_THERMAL_POLICY_QUERY = 0x4c, |
---|
101 | 91 | }; |
---|
102 | 92 | |
---|
103 | 93 | enum hp_wmi_command { |
---|
.. | .. |
---|
128 | 118 | HPWMI_POWER_SOFT = 0x02, |
---|
129 | 119 | HPWMI_POWER_BIOS = 0x04, |
---|
130 | 120 | HPWMI_POWER_HARD = 0x08, |
---|
| 121 | + HPWMI_POWER_FW_OR_HW = HPWMI_POWER_BIOS | HPWMI_POWER_HARD, |
---|
131 | 122 | }; |
---|
132 | 123 | |
---|
133 | | -#define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \ |
---|
134 | | - != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) |
---|
| 124 | +#define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW) |
---|
135 | 125 | #define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT) |
---|
136 | 126 | |
---|
137 | 127 | struct bios_rfkill2_device_state { |
---|
.. | .. |
---|
263 | 253 | ret = bios_return->return_code; |
---|
264 | 254 | |
---|
265 | 255 | if (ret) { |
---|
266 | | - if (ret != HPWMI_RET_UNKNOWN_CMDTYPE) |
---|
| 256 | + if (ret != HPWMI_RET_UNKNOWN_COMMAND && |
---|
| 257 | + ret != HPWMI_RET_UNKNOWN_CMDTYPE) |
---|
267 | 258 | pr_warn("query 0x%x returned error 0x%x\n", query, ret); |
---|
268 | 259 | goto out_free; |
---|
269 | 260 | } |
---|
.. | .. |
---|
496 | 487 | static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, |
---|
497 | 488 | const char *buf, size_t count) |
---|
498 | 489 | { |
---|
499 | | - long unsigned int tmp2; |
---|
| 490 | + u32 tmp = 1; |
---|
| 491 | + bool clear; |
---|
500 | 492 | int ret; |
---|
501 | | - u32 tmp; |
---|
502 | 493 | |
---|
503 | | - ret = kstrtoul(buf, 10, &tmp2); |
---|
504 | | - if (!ret && tmp2 != 1) |
---|
505 | | - ret = -EINVAL; |
---|
| 494 | + ret = kstrtobool(buf, &clear); |
---|
506 | 495 | if (ret) |
---|
507 | | - goto out; |
---|
| 496 | + return ret; |
---|
| 497 | + |
---|
| 498 | + if (clear == false) |
---|
| 499 | + return -EINVAL; |
---|
508 | 500 | |
---|
509 | 501 | /* Clear the POST error code. It is kept until until cleared. */ |
---|
510 | | - tmp = (u32) tmp2; |
---|
511 | 502 | ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp, |
---|
512 | 503 | sizeof(tmp), sizeof(tmp)); |
---|
513 | | - |
---|
514 | | -out: |
---|
515 | 504 | if (ret) |
---|
516 | 505 | return ret < 0 ? ret : -EINVAL; |
---|
517 | 506 | |
---|
.. | .. |
---|
524 | 513 | static DEVICE_ATTR_RO(dock); |
---|
525 | 514 | static DEVICE_ATTR_RO(tablet); |
---|
526 | 515 | static DEVICE_ATTR_RW(postcode); |
---|
| 516 | + |
---|
| 517 | +static struct attribute *hp_wmi_attrs[] = { |
---|
| 518 | + &dev_attr_display.attr, |
---|
| 519 | + &dev_attr_hddtemp.attr, |
---|
| 520 | + &dev_attr_als.attr, |
---|
| 521 | + &dev_attr_dock.attr, |
---|
| 522 | + &dev_attr_tablet.attr, |
---|
| 523 | + &dev_attr_postcode.attr, |
---|
| 524 | + NULL, |
---|
| 525 | +}; |
---|
| 526 | +ATTRIBUTE_GROUPS(hp_wmi); |
---|
527 | 527 | |
---|
528 | 528 | static void hp_wmi_notify(u32 value, void *context) |
---|
529 | 529 | { |
---|
.. | .. |
---|
631 | 631 | break; |
---|
632 | 632 | case HPWMI_BATTERY_CHARGE_PERIOD: |
---|
633 | 633 | break; |
---|
| 634 | + case HPWMI_SANITIZATION_MODE: |
---|
| 635 | + break; |
---|
| 636 | + case HPWMI_SMART_EXPERIENCE_APP: |
---|
| 637 | + break; |
---|
634 | 638 | default: |
---|
635 | 639 | pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data); |
---|
636 | 640 | break; |
---|
.. | .. |
---|
701 | 705 | { |
---|
702 | 706 | wmi_remove_notify_handler(HPWMI_EVENT_GUID); |
---|
703 | 707 | input_unregister_device(hp_wmi_input_dev); |
---|
704 | | -} |
---|
705 | | - |
---|
706 | | -static void cleanup_sysfs(struct platform_device *device) |
---|
707 | | -{ |
---|
708 | | - device_remove_file(&device->dev, &dev_attr_display); |
---|
709 | | - device_remove_file(&device->dev, &dev_attr_hddtemp); |
---|
710 | | - device_remove_file(&device->dev, &dev_attr_als); |
---|
711 | | - device_remove_file(&device->dev, &dev_attr_dock); |
---|
712 | | - device_remove_file(&device->dev, &dev_attr_tablet); |
---|
713 | | - device_remove_file(&device->dev, &dev_attr_postcode); |
---|
714 | 708 | } |
---|
715 | 709 | |
---|
716 | 710 | static int __init hp_wmi_rfkill_setup(struct platform_device *device) |
---|
.. | .. |
---|
881 | 875 | return err; |
---|
882 | 876 | } |
---|
883 | 877 | |
---|
| 878 | +static int thermal_policy_setup(struct platform_device *device) |
---|
| 879 | +{ |
---|
| 880 | + int err, tp; |
---|
| 881 | + |
---|
| 882 | + tp = hp_wmi_read_int(HPWMI_THERMAL_POLICY_QUERY); |
---|
| 883 | + if (tp < 0) |
---|
| 884 | + return tp; |
---|
| 885 | + |
---|
| 886 | + /* |
---|
| 887 | + * call thermal policy write command to ensure that the firmware correctly |
---|
| 888 | + * sets the OEM variables for the DPTF |
---|
| 889 | + */ |
---|
| 890 | + err = hp_wmi_perform_query(HPWMI_THERMAL_POLICY_QUERY, HPWMI_WRITE, &tp, |
---|
| 891 | + sizeof(tp), 0); |
---|
| 892 | + if (err) |
---|
| 893 | + return err; |
---|
| 894 | + |
---|
| 895 | + return 0; |
---|
| 896 | +} |
---|
| 897 | + |
---|
884 | 898 | static int __init hp_wmi_bios_setup(struct platform_device *device) |
---|
885 | 899 | { |
---|
886 | | - int err; |
---|
887 | | - |
---|
888 | 900 | /* clear detected rfkill devices */ |
---|
889 | 901 | wifi_rfkill = NULL; |
---|
890 | 902 | bluetooth_rfkill = NULL; |
---|
891 | 903 | wwan_rfkill = NULL; |
---|
892 | 904 | rfkill2_count = 0; |
---|
893 | 905 | |
---|
894 | | - if (hp_wmi_rfkill_setup(device)) |
---|
895 | | - hp_wmi_rfkill2_setup(device); |
---|
| 906 | + /* |
---|
| 907 | + * In pre-2009 BIOS, command 1Bh return 0x4 to indicate that |
---|
| 908 | + * BIOS no longer controls the power for the wireless |
---|
| 909 | + * devices. All features supported by this command will no |
---|
| 910 | + * longer be supported. |
---|
| 911 | + */ |
---|
| 912 | + if (!hp_wmi_bios_2009_later()) { |
---|
| 913 | + if (hp_wmi_rfkill_setup(device)) |
---|
| 914 | + hp_wmi_rfkill2_setup(device); |
---|
| 915 | + } |
---|
896 | 916 | |
---|
897 | | - err = device_create_file(&device->dev, &dev_attr_display); |
---|
898 | | - if (err) |
---|
899 | | - goto add_sysfs_error; |
---|
900 | | - err = device_create_file(&device->dev, &dev_attr_hddtemp); |
---|
901 | | - if (err) |
---|
902 | | - goto add_sysfs_error; |
---|
903 | | - err = device_create_file(&device->dev, &dev_attr_als); |
---|
904 | | - if (err) |
---|
905 | | - goto add_sysfs_error; |
---|
906 | | - err = device_create_file(&device->dev, &dev_attr_dock); |
---|
907 | | - if (err) |
---|
908 | | - goto add_sysfs_error; |
---|
909 | | - err = device_create_file(&device->dev, &dev_attr_tablet); |
---|
910 | | - if (err) |
---|
911 | | - goto add_sysfs_error; |
---|
912 | | - err = device_create_file(&device->dev, &dev_attr_postcode); |
---|
913 | | - if (err) |
---|
914 | | - goto add_sysfs_error; |
---|
| 917 | + thermal_policy_setup(device); |
---|
| 918 | + |
---|
915 | 919 | return 0; |
---|
916 | | - |
---|
917 | | -add_sysfs_error: |
---|
918 | | - cleanup_sysfs(device); |
---|
919 | | - return err; |
---|
920 | 920 | } |
---|
921 | 921 | |
---|
922 | 922 | static int __exit hp_wmi_bios_remove(struct platform_device *device) |
---|
923 | 923 | { |
---|
924 | 924 | int i; |
---|
925 | | - cleanup_sysfs(device); |
---|
926 | 925 | |
---|
927 | 926 | for (i = 0; i < rfkill2_count; i++) { |
---|
928 | 927 | rfkill_unregister(rfkill2[i].rfkill); |
---|
.. | .. |
---|
991 | 990 | .driver = { |
---|
992 | 991 | .name = "hp-wmi", |
---|
993 | 992 | .pm = &hp_wmi_pm_ops, |
---|
| 993 | + .dev_groups = hp_wmi_groups, |
---|
994 | 994 | }, |
---|
995 | 995 | .remove = __exit_p(hp_wmi_bios_remove), |
---|
996 | 996 | }; |
---|