Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'platform-drivers-x86-v4.8-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86

Pull x8 platform driver updates from Darren Hart:
"Several new quirks and tweaks for new platforms to existing laptop
drivers. A new ACPI virtual power button driver, similar to the
intel-hid driver. A rework of the dell keymap, using a single sparse
keymap for all machines. A few fixes and cleanups.

Summary:

intel-vbtn:
- new driver for Intel Virtual Button

intel_pmc_core:
- Convert to DEFINE_DEBUGFS_ATTRIBUTE

fujitsu-laptop:
- Rework brightness of eco led

asus-wmi:
- Add quirk_no_rfkill_wapf4 for the Asus X456UA
- Add quirk_no_rfkill_wapf4 for the Asus X456UF
- Add quirk_no_rfkill for the Asus Z550MA
- Add quirk_no_rfkill for the Asus U303LB
- Add quirk_no_rfkill for the Asus N552VW
- Create quirk for airplane_mode LED
- Add ambient light sensor toggle key

asus-wireless:
- Toggle airplane mode LED

intel_telemetry:
- Remove Monitor MWAIT feature dependency

intel-hid:
- Remove duplicated acpi_remove_notify_handler

fujitsu-laptop:
- Add support for eco LED
- Support touchpad toggle hotkey on Skylake-based models
- Remove unused macros
- Use module name in debug messages

hp-wmi:
- Fix wifi cannot be hard-unblocked

toshiba_acpi:
- Bump driver version and update copyright year
- Remove the position sysfs entry
- Add IIO interface for accelerometer axis data

dell-wmi:
- Add a WMI event code for display on/off
- Generate one sparse keymap for all machines
- Add information about other WMI event codes
- Sort WMI event codes and update comments
- Ignore WMI event code 0xe045"

* tag 'platform-drivers-x86-v4.8-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86: (26 commits)
intel-vbtn: new driver for Intel Virtual Button
intel_pmc_core: Convert to DEFINE_DEBUGFS_ATTRIBUTE
fujitsu-laptop: Rework brightness of eco led
asus-wmi: Add quirk_no_rfkill_wapf4 for the Asus X456UA
asus-wmi: Add quirk_no_rfkill_wapf4 for the Asus X456UF
asus-wmi: Add quirk_no_rfkill for the Asus Z550MA
asus-wmi: Add quirk_no_rfkill for the Asus U303LB
asus-wmi: Add quirk_no_rfkill for the Asus N552VW
asus-wmi: Create quirk for airplane_mode LED
asus-wireless: Toggle airplane mode LED
intel_telemetry: Remove Monitor MWAIT feature dependency
intel-hid: Remove duplicated acpi_remove_notify_handler
asus-wmi: Add ambient light sensor toggle key
fujitsu-laptop: Add support for eco LED
fujitsu-laptop: Support touchpad toggle hotkey on Skylake-based models
fujitsu-laptop: Remove unused macros
fujitsu-laptop: Use module name in debug messages
hp-wmi: Fix wifi cannot be hard-unblocked
toshiba_acpi: Bump driver version and update copyright year
toshiba_acpi: Remove the position sysfs entry
...

+723 -211
+6
MAINTAINERS
··· 5921 5921 S: Maintained 5922 5922 F: drivers/platform/x86/intel-hid.c 5923 5923 5924 + INTEL VIRTUAL BUTTON DRIVER 5925 + M: AceLan Kao <acelan.kao@canonical.com> 5926 + L: platform-driver-x86@vger.kernel.org 5927 + S: Maintained 5928 + F: drivers/platform/x86/intel-vbtn.c 5929 + 5924 5930 INTEL IDLE DRIVER 5925 5931 M: Len Brown <lenb@kernel.org> 5926 5932 L: linux-pm@vger.kernel.org
+15
drivers/platform/x86/Kconfig
··· 603 603 tristate "Asus Wireless Radio Control Driver" 604 604 depends on ACPI 605 605 depends on INPUT 606 + select NEW_LEDS 607 + select LEDS_CLASS 606 608 ---help--- 607 609 The Asus Wireless Radio Control handles the airplane mode hotkey 608 610 present on some Asus laptops. ··· 670 668 depends on SERIO_I8042 || SERIO_I8042 = n 671 669 depends on ACPI_VIDEO || ACPI_VIDEO = n 672 670 depends on RFKILL || RFKILL = n 671 + depends on IIO 673 672 select INPUT_POLLDEV 674 673 select INPUT_SPARSEKMAP 675 674 ---help--- ··· 772 769 773 770 To compile this driver as a module, choose M here: the module will 774 771 be called intel_hid. 772 + 773 + config INTEL_VBTN 774 + tristate "INTEL VIRTUAL BUTTON" 775 + depends on ACPI 776 + depends on INPUT 777 + select INPUT_SPARSEKMAP 778 + help 779 + This driver provides support for the Intel Virtual Button interface. 780 + Some laptops require this driver for power button support. 781 + 782 + To compile this driver as a module, choose M here: the module will 783 + be called intel_vbtn. 775 784 776 785 config INTEL_SCU_IPC 777 786 bool "Intel SCU IPC Support"
+1
drivers/platform/x86/Makefile
··· 44 44 obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o 45 45 obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o 46 46 obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o 47 + obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o 47 48 obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 48 49 obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o 49 50 obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
+48 -2
drivers/platform/x86/asus-nb-wmi.c
··· 78 78 .wapf = 2, 79 79 }; 80 80 81 + static struct quirk_entry quirk_no_rfkill = { 82 + .no_rfkill = true, 83 + }; 84 + 85 + static struct quirk_entry quirk_no_rfkill_wapf4 = { 86 + .wapf = 4, 87 + .no_rfkill = true, 88 + }; 89 + 81 90 static int dmi_matched(const struct dmi_system_id *dmi) 82 91 { 83 92 quirks = dmi->driver_data; ··· 142 133 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 143 134 DMI_MATCH(DMI_PRODUCT_NAME, "X456UA"), 144 135 }, 145 - .driver_data = &quirk_asus_wapf4, 136 + .driver_data = &quirk_no_rfkill_wapf4, 146 137 }, 147 138 { 148 139 .callback = dmi_matched, ··· 151 142 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 152 143 DMI_MATCH(DMI_PRODUCT_NAME, "X456UF"), 153 144 }, 154 - .driver_data = &quirk_asus_wapf4, 145 + .driver_data = &quirk_no_rfkill_wapf4, 155 146 }, 156 147 { 157 148 .callback = dmi_matched, ··· 315 306 }, 316 307 .driver_data = &quirk_asus_x200ca, 317 308 }, 309 + { 310 + .callback = dmi_matched, 311 + .ident = "ASUSTeK COMPUTER INC. X555UB", 312 + .matches = { 313 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 314 + DMI_MATCH(DMI_PRODUCT_NAME, "X555UB"), 315 + }, 316 + .driver_data = &quirk_no_rfkill, 317 + }, 318 + { 319 + .callback = dmi_matched, 320 + .ident = "ASUSTeK COMPUTER INC. N552VW", 321 + .matches = { 322 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 323 + DMI_MATCH(DMI_PRODUCT_NAME, "N552VW"), 324 + }, 325 + .driver_data = &quirk_no_rfkill, 326 + }, 327 + { 328 + .callback = dmi_matched, 329 + .ident = "ASUSTeK COMPUTER INC. U303LB", 330 + .matches = { 331 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 332 + DMI_MATCH(DMI_PRODUCT_NAME, "U303LB"), 333 + }, 334 + .driver_data = &quirk_no_rfkill, 335 + }, 336 + { 337 + .callback = dmi_matched, 338 + .ident = "ASUSTeK COMPUTER INC. Z550MA", 339 + .matches = { 340 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 341 + DMI_MATCH(DMI_PRODUCT_NAME, "Z550MA"), 342 + }, 343 + .driver_data = &quirk_no_rfkill, 344 + }, 318 345 {}, 319 346 }; 320 347 ··· 401 356 { KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */ 402 357 { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, 403 358 { KE_IGNORE, 0x6E, }, /* Low Battery notification */ 359 + { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */ 404 360 { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ 405 361 { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */ 406 362 { KE_KEY, 0x82, { KEY_CAMERA } },
+90 -1
drivers/platform/x86/asus-wireless.c
··· 15 15 #include <linux/acpi.h> 16 16 #include <linux/input.h> 17 17 #include <linux/pci_ids.h> 18 + #include <linux/leds.h> 19 + 20 + #define ASUS_WIRELESS_LED_STATUS 0x2 21 + #define ASUS_WIRELESS_LED_OFF 0x4 22 + #define ASUS_WIRELESS_LED_ON 0x5 18 23 19 24 struct asus_wireless_data { 20 25 struct input_dev *idev; 26 + struct acpi_device *adev; 27 + struct workqueue_struct *wq; 28 + struct work_struct led_work; 29 + struct led_classdev led; 30 + int led_state; 21 31 }; 32 + 33 + static u64 asus_wireless_method(acpi_handle handle, const char *method, 34 + int param) 35 + { 36 + struct acpi_object_list p; 37 + union acpi_object obj; 38 + acpi_status s; 39 + u64 ret; 40 + 41 + acpi_handle_debug(handle, "Evaluating method %s, parameter %#x\n", 42 + method, param); 43 + obj.type = ACPI_TYPE_INTEGER; 44 + obj.integer.value = param; 45 + p.count = 1; 46 + p.pointer = &obj; 47 + 48 + s = acpi_evaluate_integer(handle, (acpi_string) method, &p, &ret); 49 + if (ACPI_FAILURE(s)) 50 + acpi_handle_err(handle, 51 + "Failed to eval method %s, param %#x (%d)\n", 52 + method, param, s); 53 + acpi_handle_debug(handle, "%s returned %#x\n", method, (uint) ret); 54 + return ret; 55 + } 56 + 57 + static enum led_brightness led_state_get(struct led_classdev *led) 58 + { 59 + struct asus_wireless_data *data; 60 + int s; 61 + 62 + data = container_of(led, struct asus_wireless_data, led); 63 + s = asus_wireless_method(acpi_device_handle(data->adev), "HSWC", 64 + ASUS_WIRELESS_LED_STATUS); 65 + if (s == ASUS_WIRELESS_LED_ON) 66 + return LED_FULL; 67 + return LED_OFF; 68 + } 69 + 70 + static void led_state_update(struct work_struct *work) 71 + { 72 + struct asus_wireless_data *data; 73 + 74 + data = container_of(work, struct asus_wireless_data, led_work); 75 + asus_wireless_method(acpi_device_handle(data->adev), "HSWC", 76 + data->led_state); 77 + } 78 + 79 + static void led_state_set(struct led_classdev *led, 80 + enum led_brightness value) 81 + { 82 + struct asus_wireless_data *data; 83 + 84 + data = container_of(led, struct asus_wireless_data, led); 85 + data->led_state = value == LED_OFF ? ASUS_WIRELESS_LED_OFF : 86 + ASUS_WIRELESS_LED_ON; 87 + queue_work(data->wq, &data->led_work); 88 + } 22 89 23 90 static void asus_wireless_notify(struct acpi_device *adev, u32 event) 24 91 { ··· 104 37 static int asus_wireless_add(struct acpi_device *adev) 105 38 { 106 39 struct asus_wireless_data *data; 40 + int err; 107 41 108 42 data = devm_kzalloc(&adev->dev, sizeof(*data), GFP_KERNEL); 109 43 if (!data) ··· 120 52 data->idev->id.vendor = PCI_VENDOR_ID_ASUSTEK; 121 53 set_bit(EV_KEY, data->idev->evbit); 122 54 set_bit(KEY_RFKILL, data->idev->keybit); 123 - return input_register_device(data->idev); 55 + err = input_register_device(data->idev); 56 + if (err) 57 + return err; 58 + 59 + data->adev = adev; 60 + data->wq = create_singlethread_workqueue("asus_wireless_workqueue"); 61 + if (!data->wq) 62 + return -ENOMEM; 63 + INIT_WORK(&data->led_work, led_state_update); 64 + data->led.name = "asus-wireless::airplane"; 65 + data->led.brightness_set = led_state_set; 66 + data->led.brightness_get = led_state_get; 67 + data->led.flags = LED_CORE_SUSPENDRESUME; 68 + data->led.max_brightness = 1; 69 + err = devm_led_classdev_register(&adev->dev, &data->led); 70 + if (err) 71 + destroy_workqueue(data->wq); 72 + return err; 124 73 } 125 74 126 75 static int asus_wireless_remove(struct acpi_device *adev) 127 76 { 77 + struct asus_wireless_data *data = acpi_driver_data(adev); 78 + 79 + if (data->wq) 80 + destroy_workqueue(data->wq); 128 81 return 0; 129 82 } 130 83
+5 -3
drivers/platform/x86/asus-wmi.c
··· 2069 2069 if (err) 2070 2070 goto fail_leds; 2071 2071 2072 - err = asus_wmi_rfkill_init(asus); 2073 - if (err) 2074 - goto fail_rfkill; 2072 + if (!asus->driver->quirks->no_rfkill) { 2073 + err = asus_wmi_rfkill_init(asus); 2074 + if (err) 2075 + goto fail_rfkill; 2076 + } 2075 2077 2076 2078 /* Some Asus desktop boards export an acpi-video backlight interface, 2077 2079 stop this from showing up */
+1
drivers/platform/x86/asus-wmi.h
··· 38 38 struct asus_wmi; 39 39 40 40 struct quirk_entry { 41 + bool no_rfkill; 41 42 bool hotplug_wireless; 42 43 bool scalar_panel_brightness; 43 44 bool store_backlight_power;
+169 -124
drivers/platform/x86/dell-wmi.c
··· 80 80 }; 81 81 82 82 /* 83 + * Keymap for WMI events of type 0x0000 84 + * 83 85 * Certain keys are flagged as KE_IGNORE. All of these are either 84 86 * notifications (rather than requests for change) or are also sent 85 87 * via the keyboard controller so should not be sent again. 86 88 */ 87 - 88 - static const struct key_entry dell_wmi_legacy_keymap[] __initconst = { 89 + static const struct key_entry dell_wmi_keymap_type_0000[] __initconst = { 89 90 { KE_IGNORE, 0x003a, { KEY_CAPSLOCK } }, 90 91 91 - { KE_KEY, 0xe045, { KEY_PROG1 } }, 92 - { KE_KEY, 0xe009, { KEY_EJECTCD } }, 93 - 94 - /* These also contain the brightness level at offset 6 */ 95 - { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } }, 96 - { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } }, 92 + /* Key code is followed by brightness level */ 93 + { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } }, 94 + { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } }, 97 95 98 96 /* Battery health status button */ 99 - { KE_KEY, 0xe007, { KEY_BATTERY } }, 97 + { KE_KEY, 0xe007, { KEY_BATTERY } }, 100 98 101 - /* Radio devices state change */ 99 + /* Radio devices state change, key code is followed by other values */ 102 100 { KE_IGNORE, 0xe008, { KEY_RFKILL } }, 103 101 104 - /* The next device is at offset 6, the active devices are at 105 - offset 8 and the attached devices at offset 10 */ 106 - { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } }, 102 + { KE_KEY, 0xe009, { KEY_EJECTCD } }, 107 103 104 + /* Key code is followed by: next, active and attached devices */ 105 + { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } }, 106 + 107 + /* Key code is followed by keyboard illumination level */ 108 108 { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } }, 109 109 110 110 /* BIOS error detected */ 111 111 { KE_IGNORE, 0xe00d, { KEY_RESERVED } }, 112 112 113 + /* Unknown, defined in ACPI DSDT */ 114 + /* { KE_IGNORE, 0xe00e, { KEY_RESERVED } }, */ 115 + 113 116 /* Wifi Catcher */ 114 - { KE_KEY, 0xe011, {KEY_PROG2 } }, 117 + { KE_KEY, 0xe011, { KEY_PROG2 } }, 115 118 116 119 /* Ambient light sensor toggle */ 117 120 { KE_IGNORE, 0xe013, { KEY_RESERVED } }, 118 121 119 122 { KE_IGNORE, 0xe020, { KEY_MUTE } }, 120 123 124 + /* Unknown, defined in ACPI DSDT */ 125 + /* { KE_IGNORE, 0xe023, { KEY_RESERVED } }, */ 126 + 127 + /* Untested, Dell Instant Launch key on Inspiron 7520 */ 128 + /* { KE_IGNORE, 0xe024, { KEY_RESERVED } }, */ 129 + 121 130 /* Dell Instant Launch key */ 122 - { KE_KEY, 0xe025, { KEY_PROG4 } }, 123 - { KE_KEY, 0xe029, { KEY_PROG4 } }, 131 + { KE_KEY, 0xe025, { KEY_PROG4 } }, 124 132 125 133 /* Audio panel key */ 126 134 { KE_IGNORE, 0xe026, { KEY_RESERVED } }, 135 + 136 + /* LCD Display On/Off Control key */ 137 + { KE_KEY, 0xe027, { KEY_DISPLAYTOGGLE } }, 138 + 139 + /* Untested, Multimedia key on Dell Vostro 3560 */ 140 + /* { KE_IGNORE, 0xe028, { KEY_RESERVED } }, */ 141 + 142 + /* Dell Instant Launch key */ 143 + { KE_KEY, 0xe029, { KEY_PROG4 } }, 144 + 145 + /* Untested, Windows Mobility Center button on Inspiron 7520 */ 146 + /* { KE_IGNORE, 0xe02a, { KEY_RESERVED } }, */ 147 + 148 + /* Unknown, defined in ACPI DSDT */ 149 + /* { KE_IGNORE, 0xe02b, { KEY_RESERVED } }, */ 150 + 151 + /* Untested, Dell Audio With Preset Switch button on Inspiron 7520 */ 152 + /* { KE_IGNORE, 0xe02c, { KEY_RESERVED } }, */ 127 153 128 154 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } }, 129 155 { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } }, 130 156 { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } }, 131 157 { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } }, 132 158 { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } }, 159 + 160 + /* NIC Link is Up */ 161 + { KE_IGNORE, 0xe043, { KEY_RESERVED } }, 162 + 163 + /* NIC Link is Down */ 164 + { KE_IGNORE, 0xe044, { KEY_RESERVED } }, 165 + 166 + /* 167 + * This entry is very suspicious! 168 + * Originally Matthew Garrett created this dell-wmi driver specially for 169 + * "button with a picture of a battery" which has event code 0xe045. 170 + * Later Mario Limonciello from Dell told us that event code 0xe045 is 171 + * reported by Num Lock and should be ignored because key is send also 172 + * by keyboard controller. 173 + * So for now we will ignore this event to prevent potential double 174 + * Num Lock key press. 175 + */ 133 176 { KE_IGNORE, 0xe045, { KEY_NUMLOCK } }, 177 + 178 + /* Scroll lock and also going to tablet mode on portable devices */ 134 179 { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } }, 180 + 181 + /* Untested, going from tablet mode on portable devices */ 182 + /* { KE_IGNORE, 0xe047, { KEY_RESERVED } }, */ 183 + 184 + /* Dell Support Center key */ 185 + { KE_IGNORE, 0xe06e, { KEY_RESERVED } }, 186 + 135 187 { KE_IGNORE, 0xe0f7, { KEY_MUTE } }, 136 188 { KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } }, 137 189 { KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } }, 138 - { KE_END, 0 } 139 190 }; 140 - 141 - static bool dell_new_hk_type; 142 191 143 192 struct dell_bios_keymap_entry { 144 193 u16 scancode; ··· 202 153 203 154 struct dell_dmi_results { 204 155 int err; 156 + int keymap_size; 205 157 struct key_entry *keymap; 206 158 }; 207 159 ··· 251 201 }; 252 202 253 203 /* 204 + * Keymap for WMI events of type 0x0010 205 + * 254 206 * These are applied if the 0xB2 DMI hotkey table is present and doesn't 255 207 * override them. 256 208 */ 257 - static const struct key_entry dell_wmi_extra_keymap[] __initconst = { 209 + static const struct key_entry dell_wmi_keymap_type_0010[] __initconst = { 258 210 /* Fn-lock */ 259 211 { KE_IGNORE, 0x151, { KEY_RESERVED } }, 260 212 ··· 276 224 { KE_IGNORE, 0x155, { KEY_RESERVED } }, 277 225 }; 278 226 227 + /* 228 + * Keymap for WMI events of type 0x0011 229 + */ 230 + static const struct key_entry dell_wmi_keymap_type_0011[] __initconst = { 231 + /* Battery unplugged */ 232 + { KE_IGNORE, 0xfff0, { KEY_RESERVED } }, 233 + 234 + /* Battery inserted */ 235 + { KE_IGNORE, 0xfff1, { KEY_RESERVED } }, 236 + 237 + /* Keyboard backlight level changed */ 238 + { KE_IGNORE, 0x01e1, { KEY_RESERVED } }, 239 + { KE_IGNORE, 0x02ea, { KEY_RESERVED } }, 240 + { KE_IGNORE, 0x02eb, { KEY_RESERVED } }, 241 + { KE_IGNORE, 0x02ec, { KEY_RESERVED } }, 242 + { KE_IGNORE, 0x02f6, { KEY_RESERVED } }, 243 + }; 244 + 279 245 static struct input_dev *dell_wmi_input_dev; 280 246 281 - static void dell_wmi_process_key(int reported_key) 247 + static void dell_wmi_process_key(int type, int code) 282 248 { 283 249 const struct key_entry *key; 284 250 285 251 key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev, 286 - reported_key); 252 + (type << 16) | code); 287 253 if (!key) { 288 - pr_info("Unknown key with scancode 0x%x pressed\n", 289 - reported_key); 254 + pr_info("Unknown key with type 0x%04x and code 0x%04x pressed\n", 255 + type, code); 290 256 return; 291 257 } 292 258 293 - pr_debug("Key %x pressed\n", reported_key); 259 + pr_debug("Key with type 0x%04x and code 0x%04x pressed\n", type, code); 294 260 295 261 /* Don't report brightness notifications that will also come via ACPI */ 296 262 if ((key->keycode == KEY_BRIGHTNESSUP || ··· 316 246 acpi_video_handles_brightness_key_presses()) 317 247 return; 318 248 319 - if (reported_key == 0xe025 && !wmi_requires_smbios_request) 249 + if (type == 0x0000 && code == 0xe025 && !wmi_requires_smbios_request) 320 250 return; 321 251 322 252 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true); ··· 354 284 355 285 buffer_entry = (u16 *)obj->buffer.pointer; 356 286 buffer_size = obj->buffer.length/2; 357 - 358 - if (!dell_new_hk_type) { 359 - if (buffer_size >= 3 && buffer_entry[1] == 0x0) 360 - dell_wmi_process_key(buffer_entry[2]); 361 - else if (buffer_size >= 2) 362 - dell_wmi_process_key(buffer_entry[1]); 363 - else 364 - pr_info("Received unknown WMI event\n"); 365 - kfree(obj); 366 - return; 367 - } 368 - 369 287 buffer_end = buffer_entry + buffer_size; 370 288 371 289 /* ··· 388 330 pr_debug("Process buffer (%*ph)\n", len*2, buffer_entry); 389 331 390 332 switch (buffer_entry[1]) { 391 - case 0x00: 392 - for (i = 2; i < len; ++i) { 393 - switch (buffer_entry[i]) { 394 - case 0xe043: 395 - /* NIC Link is Up */ 396 - pr_debug("NIC Link is Up\n"); 397 - break; 398 - case 0xe044: 399 - /* NIC Link is Down */ 400 - pr_debug("NIC Link is Down\n"); 401 - break; 402 - case 0xe045: 403 - /* Unknown event but defined in DSDT */ 404 - default: 405 - /* Unknown event */ 406 - pr_info("Unknown WMI event type 0x00: " 407 - "0x%x\n", (int)buffer_entry[i]); 408 - break; 409 - } 410 - } 333 + case 0x0000: /* One key pressed or event occurred */ 334 + if (len > 2) 335 + dell_wmi_process_key(0x0000, buffer_entry[2]); 336 + /* Other entries could contain additional information */ 411 337 break; 412 - case 0x10: 413 - /* Keys pressed */ 338 + case 0x0010: /* Sequence of keys pressed */ 339 + case 0x0011: /* Sequence of events occurred */ 414 340 for (i = 2; i < len; ++i) 415 - dell_wmi_process_key(buffer_entry[i]); 341 + dell_wmi_process_key(buffer_entry[1], 342 + buffer_entry[i]); 416 343 break; 417 - case 0x11: 418 - for (i = 2; i < len; ++i) { 419 - switch (buffer_entry[i]) { 420 - case 0xfff0: 421 - /* Battery unplugged */ 422 - pr_debug("Battery unplugged\n"); 423 - break; 424 - case 0xfff1: 425 - /* Battery inserted */ 426 - pr_debug("Battery inserted\n"); 427 - break; 428 - case 0x01e1: 429 - case 0x02ea: 430 - case 0x02eb: 431 - case 0x02ec: 432 - case 0x02f6: 433 - /* Keyboard backlight level changed */ 434 - pr_debug("Keyboard backlight level " 435 - "changed\n"); 436 - break; 437 - default: 438 - /* Unknown event */ 439 - pr_info("Unknown WMI event type 0x11: " 440 - "0x%x\n", (int)buffer_entry[i]); 441 - break; 442 - } 443 - } 444 - break; 445 - default: 446 - /* Unknown event */ 344 + default: /* Unknown event */ 447 345 pr_info("Unknown WMI event type 0x%x\n", 448 346 (int)buffer_entry[1]); 449 347 break; ··· 424 410 } 425 411 426 412 static void __init handle_dmi_entry(const struct dmi_header *dm, 427 - 428 413 void *opaque) 429 414 430 415 { ··· 431 418 struct dell_bios_hotkey_table *table; 432 419 int hotkey_num, i, pos = 0; 433 420 struct key_entry *keymap; 434 - int num_bios_keys; 435 421 436 422 if (results->err || results->keymap) 437 423 return; /* We already found the hotkey table. */ ··· 454 442 return; 455 443 } 456 444 457 - keymap = kcalloc(hotkey_num + ARRAY_SIZE(dell_wmi_extra_keymap) + 1, 458 - sizeof(struct key_entry), GFP_KERNEL); 445 + keymap = kcalloc(hotkey_num, sizeof(struct key_entry), GFP_KERNEL); 459 446 if (!keymap) { 460 447 results->err = -ENOMEM; 461 448 return; ··· 491 480 pos++; 492 481 } 493 482 494 - num_bios_keys = pos; 495 - 496 - for (i = 0; i < ARRAY_SIZE(dell_wmi_extra_keymap); i++) { 497 - const struct key_entry *entry = &dell_wmi_extra_keymap[i]; 498 - 499 - /* 500 - * Check if we've already found this scancode. This takes 501 - * quadratic time, but it doesn't matter unless the list 502 - * of extra keys gets very long. 503 - */ 504 - if (!have_scancode(entry->code, keymap, num_bios_keys)) { 505 - keymap[pos] = *entry; 506 - pos++; 507 - } 508 - } 509 - 510 - keymap[pos].type = KE_END; 511 - 512 483 results->keymap = keymap; 484 + results->keymap_size = pos; 513 485 } 514 486 515 487 static int __init dell_wmi_input_setup(void) 516 488 { 517 489 struct dell_dmi_results dmi_results = {}; 518 - int err; 490 + struct key_entry *keymap; 491 + int err, i, pos = 0; 519 492 520 493 dell_wmi_input_dev = input_allocate_device(); 521 494 if (!dell_wmi_input_dev) ··· 523 528 goto err_free_dev; 524 529 } 525 530 526 - if (dmi_results.keymap) { 527 - dell_new_hk_type = true; 531 + keymap = kcalloc(dmi_results.keymap_size + 532 + ARRAY_SIZE(dell_wmi_keymap_type_0000) + 533 + ARRAY_SIZE(dell_wmi_keymap_type_0010) + 534 + ARRAY_SIZE(dell_wmi_keymap_type_0011) + 535 + 1, 536 + sizeof(struct key_entry), GFP_KERNEL); 537 + if (!keymap) { 538 + kfree(dmi_results.keymap); 539 + err = -ENOMEM; 540 + goto err_free_dev; 541 + } 528 542 529 - err = sparse_keymap_setup(dell_wmi_input_dev, 530 - dmi_results.keymap, NULL); 543 + /* Append table with events of type 0x0010 which comes from DMI */ 544 + for (i = 0; i < dmi_results.keymap_size; i++) { 545 + keymap[pos] = dmi_results.keymap[i]; 546 + keymap[pos].code |= (0x0010 << 16); 547 + pos++; 548 + } 549 + 550 + kfree(dmi_results.keymap); 551 + 552 + /* Append table with extra events of type 0x0010 which are not in DMI */ 553 + for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0010); i++) { 554 + const struct key_entry *entry = &dell_wmi_keymap_type_0010[i]; 531 555 532 556 /* 533 - * Sparse keymap library makes a copy of keymap so we 534 - * don't need the original one that was allocated. 557 + * Check if we've already found this scancode. This takes 558 + * quadratic time, but it doesn't matter unless the list 559 + * of extra keys gets very long. 535 560 */ 536 - kfree(dmi_results.keymap); 537 - } else { 538 - err = sparse_keymap_setup(dell_wmi_input_dev, 539 - dell_wmi_legacy_keymap, NULL); 561 + if (dmi_results.keymap_size && 562 + have_scancode(entry->code | (0x0010 << 16), 563 + keymap, dmi_results.keymap_size) 564 + ) 565 + continue; 566 + 567 + keymap[pos] = *entry; 568 + keymap[pos].code |= (0x0010 << 16); 569 + pos++; 540 570 } 571 + 572 + /* Append table with events of type 0x0011 */ 573 + for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0011); i++) { 574 + keymap[pos] = dell_wmi_keymap_type_0011[i]; 575 + keymap[pos].code |= (0x0011 << 16); 576 + pos++; 577 + } 578 + 579 + /* 580 + * Now append also table with "legacy" events of type 0x0000. Some of 581 + * them are reported also on laptops which have scancodes in DMI. 582 + */ 583 + for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0000); i++) { 584 + keymap[pos] = dell_wmi_keymap_type_0000[i]; 585 + pos++; 586 + } 587 + 588 + keymap[pos].type = KE_END; 589 + 590 + err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL); 591 + /* 592 + * Sparse keymap library makes a copy of keymap so we don't need the 593 + * original one that was allocated. 594 + */ 595 + kfree(keymap); 541 596 if (err) 542 597 goto err_free_dev; 543 598
+70 -11
drivers/platform/x86/fujitsu-laptop.c
··· 88 88 89 89 #define ACPI_FUJITSU_NOTIFY_CODE1 0x80 90 90 91 - #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 92 - #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 93 - 94 91 /* FUNC interface - command values */ 95 92 #define FUNC_RFKILL 0x1000 96 93 #define FUNC_LEDS 0x1001 ··· 105 108 #define LOGOLAMP_POWERON 0x2000 106 109 #define LOGOLAMP_ALWAYS 0x4000 107 110 #define RADIO_LED_ON 0x20 111 + #define ECO_LED 0x10000 112 + #define ECO_LED_ON 0x80000 108 113 #endif 109 114 110 115 /* Hotkey details */ ··· 120 121 #define RINGBUFFERSIZE 40 121 122 122 123 /* Debugging */ 123 - #define FUJLAPTOP_LOG ACPI_FUJITSU_HID ": " 124 - #define FUJLAPTOP_ERR KERN_ERR FUJLAPTOP_LOG 125 - #define FUJLAPTOP_NOTICE KERN_NOTICE FUJLAPTOP_LOG 126 - #define FUJLAPTOP_INFO KERN_INFO FUJLAPTOP_LOG 127 - #define FUJLAPTOP_DEBUG KERN_DEBUG FUJLAPTOP_LOG 128 - 129 - #define FUJLAPTOP_DBG_ALL 0xffff 130 124 #define FUJLAPTOP_DBG_ERROR 0x0001 131 125 #define FUJLAPTOP_DBG_WARN 0x0002 132 126 #define FUJLAPTOP_DBG_INFO 0x0004 ··· 128 136 #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 129 137 #define vdbg_printk(a_dbg_level, format, arg...) \ 130 138 do { if (dbg_level & a_dbg_level) \ 131 - printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ 139 + printk(KERN_DEBUG pr_fmt("%s: " format), __func__, ## arg); \ 132 140 } while (0) 133 141 #else 134 142 #define vdbg_printk(a_dbg_level, format, arg...) \ ··· 168 176 int logolamp_registered; 169 177 int kblamps_registered; 170 178 int radio_led_registered; 179 + int eco_led_registered; 171 180 }; 172 181 173 182 static struct fujitsu_hotkey_t *fujitsu_hotkey; ··· 204 211 .name = "fujitsu::radio_led", 205 212 .brightness_get = radio_led_get, 206 213 .brightness_set = radio_led_set 214 + }; 215 + 216 + static enum led_brightness eco_led_get(struct led_classdev *cdev); 217 + static void eco_led_set(struct led_classdev *cdev, 218 + enum led_brightness brightness); 219 + 220 + static struct led_classdev eco_led = { 221 + .name = "fujitsu::eco_led", 222 + .brightness_get = eco_led_get, 223 + .brightness_set = eco_led_set 207 224 }; 208 225 #endif 209 226 ··· 299 296 call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0); 300 297 } 301 298 299 + static void eco_led_set(struct led_classdev *cdev, 300 + enum led_brightness brightness) 301 + { 302 + int curr; 303 + 304 + curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0); 305 + if (brightness >= LED_FULL) 306 + call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON); 307 + else 308 + call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON); 309 + } 310 + 302 311 static enum led_brightness logolamp_get(struct led_classdev *cdev) 303 312 { 304 313 enum led_brightness brightness = LED_OFF; ··· 341 326 enum led_brightness brightness = LED_OFF; 342 327 343 328 if (call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0) & RADIO_LED_ON) 329 + brightness = LED_FULL; 330 + 331 + return brightness; 332 + } 333 + 334 + static enum led_brightness eco_led_get(struct led_classdev *cdev) 335 + { 336 + enum led_brightness brightness = LED_OFF; 337 + 338 + if (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON) 344 339 brightness = LED_FULL; 345 340 346 341 return brightness; ··· 881 856 set_bit(fujitsu->keycode3, input->keybit); 882 857 set_bit(fujitsu->keycode4, input->keybit); 883 858 set_bit(fujitsu->keycode5, input->keybit); 859 + set_bit(KEY_TOUCHPAD_TOGGLE, input->keybit); 884 860 set_bit(KEY_UNKNOWN, input->keybit); 885 861 886 862 error = input_register_device(input); ··· 969 943 result); 970 944 } 971 945 } 946 + 947 + /* Support for eco led is not always signaled in bit corresponding 948 + * to the bit used to control the led. According to the DSDT table, 949 + * bit 14 seems to indicate presence of said led as well. 950 + * Confirm by testing the status. 951 + */ 952 + if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) && 953 + (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) { 954 + result = led_classdev_register(&fujitsu->pf_device->dev, 955 + &eco_led); 956 + if (result == 0) { 957 + fujitsu_hotkey->eco_led_registered = 1; 958 + } else { 959 + pr_err("Could not register LED handler for eco LED, error %i\n", 960 + result); 961 + } 962 + } 972 963 #endif 973 964 974 965 return result; ··· 1015 972 1016 973 if (fujitsu_hotkey->radio_led_registered) 1017 974 led_classdev_unregister(&radio_led); 975 + 976 + if (fujitsu_hotkey->eco_led_registered) 977 + led_classdev_unregister(&eco_led); 1018 978 #endif 1019 979 1020 980 input_unregister_device(input); ··· 1104 1058 keycode_r); 1105 1059 } 1106 1060 } 1061 + } 1062 + 1063 + /* On some models (first seen on the Skylake-based Lifebook 1064 + * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is 1065 + * handled in software; its state is queried using FUNC_RFKILL 1066 + */ 1067 + if ((fujitsu_hotkey->rfkill_supported & BIT(26)) && 1068 + (call_fext_func(FUNC_RFKILL, 0x1, 0x0, 0x0) & BIT(26))) { 1069 + keycode = KEY_TOUCHPAD_TOGGLE; 1070 + input_report_key(input, keycode, 1); 1071 + input_sync(input); 1072 + input_report_key(input, keycode, 0); 1073 + input_sync(input); 1107 1074 } 1108 1075 1109 1076 break;
+6 -1
drivers/platform/x86/hp-wmi.c
··· 718 718 if (err) 719 719 return err; 720 720 721 + err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, &wireless, 722 + sizeof(wireless), 0); 723 + if (err) 724 + return err; 725 + 721 726 if (wireless & 0x1) { 722 727 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 723 728 RFKILL_TYPE_WLAN, ··· 887 882 wwan_rfkill = NULL; 888 883 rfkill2_count = 0; 889 884 890 - if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device)) 885 + if (hp_wmi_rfkill_setup(device)) 891 886 hp_wmi_rfkill2_setup(device); 892 887 893 888 err = device_create_file(&device->dev, &dev_attr_display);
+2 -3
drivers/platform/x86/intel-hid.c
··· 122 122 return 0; 123 123 124 124 err_free_device: 125 - input_free_device(priv->input_dev); 126 - return ret; 125 + input_free_device(priv->input_dev); 126 + return ret; 127 127 } 128 128 129 129 static void intel_hid_input_destroy(struct platform_device *device) ··· 224 224 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 225 225 intel_hid_input_destroy(device); 226 226 intel_hid_set_enable(&device->dev, 0); 227 - acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 228 227 229 228 /* 230 229 * Even if we failed to shut off the event stream, we can still
+188
drivers/platform/x86/intel-vbtn.c
··· 1 + /* 2 + * Intel Virtual Button driver for Windows 8.1+ 3 + * 4 + * Copyright (C) 2016 AceLan Kao <acelan.kao@canonical.com> 5 + * Copyright (C) 2016 Alex Hung <alex.hung@canonical.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + */ 18 + 19 + #include <linux/kernel.h> 20 + #include <linux/module.h> 21 + #include <linux/init.h> 22 + #include <linux/input.h> 23 + #include <linux/platform_device.h> 24 + #include <linux/input/sparse-keymap.h> 25 + #include <linux/acpi.h> 26 + #include <acpi/acpi_bus.h> 27 + 28 + MODULE_LICENSE("GPL"); 29 + MODULE_AUTHOR("AceLan Kao"); 30 + 31 + static const struct acpi_device_id intel_vbtn_ids[] = { 32 + {"INT33D6", 0}, 33 + {"", 0}, 34 + }; 35 + 36 + /* In theory, these are HID usages. */ 37 + static const struct key_entry intel_vbtn_keymap[] = { 38 + { KE_IGNORE, 0xC0, { KEY_POWER } }, /* power key press */ 39 + { KE_KEY, 0xC1, { KEY_POWER } }, /* power key release */ 40 + { KE_END }, 41 + }; 42 + 43 + struct intel_vbtn_priv { 44 + struct input_dev *input_dev; 45 + }; 46 + 47 + static int intel_vbtn_input_setup(struct platform_device *device) 48 + { 49 + struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); 50 + int ret; 51 + 52 + priv->input_dev = input_allocate_device(); 53 + if (!priv->input_dev) 54 + return -ENOMEM; 55 + 56 + ret = sparse_keymap_setup(priv->input_dev, intel_vbtn_keymap, NULL); 57 + if (ret) 58 + goto err_free_device; 59 + 60 + priv->input_dev->dev.parent = &device->dev; 61 + priv->input_dev->name = "Intel Virtual Button driver"; 62 + priv->input_dev->id.bustype = BUS_HOST; 63 + 64 + ret = input_register_device(priv->input_dev); 65 + if (ret) 66 + goto err_free_device; 67 + 68 + return 0; 69 + 70 + err_free_device: 71 + input_free_device(priv->input_dev); 72 + return ret; 73 + } 74 + 75 + static void intel_vbtn_input_destroy(struct platform_device *device) 76 + { 77 + struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); 78 + 79 + input_unregister_device(priv->input_dev); 80 + } 81 + 82 + static void notify_handler(acpi_handle handle, u32 event, void *context) 83 + { 84 + struct platform_device *device = context; 85 + struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); 86 + 87 + if (!sparse_keymap_report_event(priv->input_dev, event, 1, true)) 88 + dev_info(&device->dev, "unknown event index 0x%x\n", 89 + event); 90 + } 91 + 92 + static int intel_vbtn_probe(struct platform_device *device) 93 + { 94 + acpi_handle handle = ACPI_HANDLE(&device->dev); 95 + struct intel_vbtn_priv *priv; 96 + acpi_status status; 97 + int err; 98 + 99 + status = acpi_evaluate_object(handle, "VBDL", NULL, NULL); 100 + if (!ACPI_SUCCESS(status)) { 101 + dev_warn(&device->dev, "failed to read Intel Virtual Button driver\n"); 102 + return -ENODEV; 103 + } 104 + 105 + priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL); 106 + if (!priv) 107 + return -ENOMEM; 108 + dev_set_drvdata(&device->dev, priv); 109 + 110 + err = intel_vbtn_input_setup(device); 111 + if (err) { 112 + pr_err("Failed to setup Intel Virtual Button\n"); 113 + return err; 114 + } 115 + 116 + status = acpi_install_notify_handler(handle, 117 + ACPI_DEVICE_NOTIFY, 118 + notify_handler, 119 + device); 120 + if (ACPI_FAILURE(status)) { 121 + err = -EBUSY; 122 + goto err_remove_input; 123 + } 124 + 125 + return 0; 126 + 127 + err_remove_input: 128 + intel_vbtn_input_destroy(device); 129 + 130 + return err; 131 + } 132 + 133 + static int intel_vbtn_remove(struct platform_device *device) 134 + { 135 + acpi_handle handle = ACPI_HANDLE(&device->dev); 136 + 137 + intel_vbtn_input_destroy(device); 138 + acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 139 + 140 + /* 141 + * Even if we failed to shut off the event stream, we can still 142 + * safely detach from the device. 143 + */ 144 + return 0; 145 + } 146 + 147 + static struct platform_driver intel_vbtn_pl_driver = { 148 + .driver = { 149 + .name = "intel-vbtn", 150 + .acpi_match_table = intel_vbtn_ids, 151 + }, 152 + .probe = intel_vbtn_probe, 153 + .remove = intel_vbtn_remove, 154 + }; 155 + MODULE_DEVICE_TABLE(acpi, intel_vbtn_ids); 156 + 157 + static acpi_status __init 158 + check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) 159 + { 160 + const struct acpi_device_id *ids = context; 161 + struct acpi_device *dev; 162 + 163 + if (acpi_bus_get_device(handle, &dev) != 0) 164 + return AE_OK; 165 + 166 + if (acpi_match_device_ids(dev, ids) == 0) 167 + if (acpi_create_platform_device(dev)) 168 + dev_info(&dev->dev, 169 + "intel-vbtn: created platform device\n"); 170 + 171 + return AE_OK; 172 + } 173 + 174 + static int __init intel_vbtn_init(void) 175 + { 176 + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 177 + ACPI_UINT32_MAX, check_acpi_dev, NULL, 178 + (void *)intel_vbtn_ids, NULL); 179 + 180 + return platform_driver_register(&intel_vbtn_pl_driver); 181 + } 182 + module_init(intel_vbtn_init); 183 + 184 + static void __exit intel_vbtn_exit(void) 185 + { 186 + platform_driver_unregister(&intel_vbtn_pl_driver); 187 + } 188 + module_exit(intel_vbtn_exit);
+10 -35
drivers/platform/x86/intel_pmc_core.c
··· 23 23 #include <linux/init.h> 24 24 #include <linux/io.h> 25 25 #include <linux/pci.h> 26 - #include <linux/seq_file.h> 27 26 28 27 #include <asm/cpu_device_id.h> 29 28 #include <asm/intel-family.h> ··· 77 78 } 78 79 EXPORT_SYMBOL_GPL(intel_pmc_slp_s0_counter_read); 79 80 80 - #if IS_ENABLED(CONFIG_DEBUG_FS) 81 - static int pmc_core_dev_state_show(struct seq_file *s, void *unused) 81 + static int pmc_core_dev_state_get(void *data, u64 *val) 82 82 { 83 - struct pmc_dev *pmcdev = s->private; 84 - u32 counter_val; 83 + struct pmc_dev *pmcdev = data; 84 + u32 value; 85 85 86 - counter_val = pmc_core_reg_read(pmcdev, 87 - SPT_PMC_SLP_S0_RES_COUNTER_OFFSET); 88 - seq_printf(s, "%u\n", pmc_core_adjust_slp_s0_step(counter_val)); 86 + value = pmc_core_reg_read(pmcdev, SPT_PMC_SLP_S0_RES_COUNTER_OFFSET); 87 + *val = pmc_core_adjust_slp_s0_step(value); 89 88 90 89 return 0; 91 90 } 92 91 93 - static int pmc_core_dev_state_open(struct inode *inode, struct file *file) 94 - { 95 - return single_open(file, pmc_core_dev_state_show, inode->i_private); 96 - } 97 - 98 - static const struct file_operations pmc_core_dev_state_ops = { 99 - .open = pmc_core_dev_state_open, 100 - .read = seq_read, 101 - .llseek = seq_lseek, 102 - .release = single_release, 103 - }; 92 + DEFINE_DEBUGFS_ATTRIBUTE(pmc_core_dev_state, pmc_core_dev_state_get, NULL, "%llu\n"); 104 93 105 94 static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) 106 95 { ··· 100 113 struct dentry *dir, *file; 101 114 102 115 dir = debugfs_create_dir("pmc_core", NULL); 103 - if (!dir) 116 + if (IS_ERR_OR_NULL(dir)) 104 117 return -ENOMEM; 105 118 106 119 pmcdev->dbgfs_dir = dir; 107 120 file = debugfs_create_file("slp_s0_residency_usec", S_IFREG | S_IRUGO, 108 - dir, pmcdev, &pmc_core_dev_state_ops); 121 + dir, pmcdev, &pmc_core_dev_state); 109 122 110 123 if (!file) { 111 124 pmc_core_dbgfs_unregister(pmcdev); ··· 114 127 115 128 return 0; 116 129 } 117 - #else 118 - static inline int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) 119 - { 120 - return 0; 121 - } 122 - 123 - static inline void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) 124 - { 125 - } 126 - #endif /* CONFIG_DEBUG_FS */ 127 130 128 131 static const struct x86_cpu_id intel_pmc_core_ids[] = { 129 132 { X86_VENDOR_INTEL, 6, INTEL_FAM6_SKYLAKE_MOBILE, X86_FEATURE_MWAIT, ··· 160 183 } 161 184 162 185 err = pmc_core_dbgfs_register(pmcdev); 163 - if (err < 0) { 164 - dev_err(&dev->dev, "PMC Core: debugfs register failed.\n"); 165 - return err; 166 - } 186 + if (err < 0) 187 + dev_warn(&dev->dev, "PMC Core: debugfs register failed.\n"); 167 188 168 189 pmc.has_slp_s0_res = true; 169 190 return 0;
+1 -2
drivers/platform/x86/intel_pmc_core.h
··· 23 23 24 24 /* Sunrise Point Power Management Controller PCI Device ID */ 25 25 #define SPT_PMC_PCI_DEVICE_ID 0x9d21 26 + 26 27 #define SPT_PMC_BASE_ADDR_OFFSET 0x48 27 28 #define SPT_PMC_SLP_S0_RES_COUNTER_OFFSET 0x13c 28 29 #define SPT_PMC_MMIO_REG_LEN 0x100 ··· 43 42 struct pmc_dev { 44 43 u32 base_addr; 45 44 void __iomem *regbase; 46 - #if IS_ENABLED(CONFIG_DEBUG_FS) 47 45 struct dentry *dbgfs_dir; 48 - #endif /* CONFIG_DEBUG_FS */ 49 46 bool has_slp_s0_res; 50 47 }; 51 48
+1 -1
drivers/platform/x86/intel_telemetry_debugfs.c
··· 79 79 #define TELEM_EVT_LEN(x) (sizeof(x)/sizeof((x)[0])) 80 80 81 81 #define TELEM_DEBUGFS_CPU(model, data) \ 82 - { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&data} 82 + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&data} 83 83 84 84 #define TELEM_CHECK_AND_PARSE_EVTS(EVTID, EVTNUM, BUF, EVTLOG, EVTDAT, MASK) { \ 85 85 if (evtlog[index].telem_evtid == (EVTID)) { \
+1 -1
drivers/platform/x86/intel_telemetry_pltdrv.c
··· 83 83 #define TELEM_SET_VERBOSITY_BITS(x, y) ((x) |= ((y) << 27)) 84 84 85 85 #define TELEM_CPU(model, data) \ 86 - { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&data } 86 + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&data } 87 87 88 88 enum telemetry_action { 89 89 TELEM_UPDATE = 0,
+109 -27
drivers/platform/x86/toshiba_acpi.c
··· 4 4 * Copyright (C) 2002-2004 John Belmonte 5 5 * Copyright (C) 2008 Philip Langdale 6 6 * Copyright (C) 2010 Pierre Ducroquet 7 - * Copyright (C) 2014-2015 Azael Avalos 7 + * Copyright (C) 2014-2016 Azael Avalos 8 8 * 9 9 * This program is free software; you can redistribute it and/or modify 10 10 * it under the terms of the GNU General Public License as published by ··· 31 31 32 32 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 33 33 34 - #define TOSHIBA_ACPI_VERSION "0.23" 34 + #define TOSHIBA_ACPI_VERSION "0.24" 35 35 #define PROC_INTERFACE_VERSION 1 36 36 37 37 #include <linux/kernel.h> ··· 53 53 #include <linux/uaccess.h> 54 54 #include <linux/miscdevice.h> 55 55 #include <linux/rfkill.h> 56 + #include <linux/iio/iio.h> 56 57 #include <linux/toshiba.h> 57 58 #include <acpi/video.h> 58 59 ··· 135 134 136 135 /* Field definitions */ 137 136 #define HCI_ACCEL_MASK 0x7fff 137 + #define HCI_ACCEL_DIRECTION_MASK 0x8000 138 138 #define HCI_HOTKEY_DISABLE 0x0b 139 139 #define HCI_HOTKEY_ENABLE 0x09 140 140 #define HCI_HOTKEY_SPECIAL_FUNCTIONS 0x10 ··· 180 178 struct led_classdev eco_led; 181 179 struct miscdevice miscdev; 182 180 struct rfkill *wwan_rfk; 181 + struct iio_dev *indio_dev; 183 182 184 183 int force_fan; 185 184 int last_key_event; ··· 1961 1958 } 1962 1959 static DEVICE_ATTR_RW(touchpad); 1963 1960 1964 - static ssize_t position_show(struct device *dev, 1965 - struct device_attribute *attr, char *buf) 1966 - { 1967 - struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); 1968 - u32 xyval, zval, tmp; 1969 - u16 x, y, z; 1970 - int ret; 1971 - 1972 - xyval = zval = 0; 1973 - ret = toshiba_accelerometer_get(toshiba, &xyval, &zval); 1974 - if (ret < 0) 1975 - return ret; 1976 - 1977 - x = xyval & HCI_ACCEL_MASK; 1978 - tmp = xyval >> HCI_MISC_SHIFT; 1979 - y = tmp & HCI_ACCEL_MASK; 1980 - z = zval & HCI_ACCEL_MASK; 1981 - 1982 - return sprintf(buf, "%d %d %d\n", x, y, z); 1983 - } 1984 - static DEVICE_ATTR_RO(position); 1985 - 1986 1961 static ssize_t usb_sleep_charge_show(struct device *dev, 1987 1962 struct device_attribute *attr, char *buf) 1988 1963 { ··· 2331 2350 &dev_attr_available_kbd_modes.attr, 2332 2351 &dev_attr_kbd_backlight_timeout.attr, 2333 2352 &dev_attr_touchpad.attr, 2334 - &dev_attr_position.attr, 2335 2353 &dev_attr_usb_sleep_charge.attr, 2336 2354 &dev_attr_sleep_functions_on_battery.attr, 2337 2355 &dev_attr_usb_rapid_charge.attr, ··· 2357 2377 exists = (drv->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false; 2358 2378 else if (attr == &dev_attr_touchpad.attr) 2359 2379 exists = (drv->touchpad_supported) ? true : false; 2360 - else if (attr == &dev_attr_position.attr) 2361 - exists = (drv->accelerometer_supported) ? true : false; 2362 2380 else if (attr == &dev_attr_usb_sleep_charge.attr) 2363 2381 exists = (drv->usb_sleep_charge_supported) ? true : false; 2364 2382 else if (attr == &dev_attr_sleep_functions_on_battery.attr) ··· 2396 2418 dev_name(&acpi_dev->dev), 2397 2419 0x92, 0); 2398 2420 } 2421 + 2422 + /* 2423 + * IIO device 2424 + */ 2425 + 2426 + enum toshiba_iio_accel_chan { 2427 + AXIS_X, 2428 + AXIS_Y, 2429 + AXIS_Z 2430 + }; 2431 + 2432 + static int toshiba_iio_accel_get_axis(enum toshiba_iio_accel_chan chan) 2433 + { 2434 + u32 xyval, zval; 2435 + int ret; 2436 + 2437 + ret = toshiba_accelerometer_get(toshiba_acpi, &xyval, &zval); 2438 + if (ret < 0) 2439 + return ret; 2440 + 2441 + switch (chan) { 2442 + case AXIS_X: 2443 + return xyval & HCI_ACCEL_DIRECTION_MASK ? 2444 + -(xyval & HCI_ACCEL_MASK) : xyval & HCI_ACCEL_MASK; 2445 + case AXIS_Y: 2446 + return (xyval >> HCI_MISC_SHIFT) & HCI_ACCEL_DIRECTION_MASK ? 2447 + -((xyval >> HCI_MISC_SHIFT) & HCI_ACCEL_MASK) : 2448 + (xyval >> HCI_MISC_SHIFT) & HCI_ACCEL_MASK; 2449 + case AXIS_Z: 2450 + return zval & HCI_ACCEL_DIRECTION_MASK ? 2451 + -(zval & HCI_ACCEL_MASK) : zval & HCI_ACCEL_MASK; 2452 + } 2453 + 2454 + return ret; 2455 + } 2456 + 2457 + static int toshiba_iio_accel_read_raw(struct iio_dev *indio_dev, 2458 + struct iio_chan_spec const *chan, 2459 + int *val, int *val2, long mask) 2460 + { 2461 + int ret; 2462 + 2463 + switch (mask) { 2464 + case IIO_CHAN_INFO_RAW: 2465 + ret = toshiba_iio_accel_get_axis(chan->channel); 2466 + if (ret == -EIO || ret == -ENODEV) 2467 + return ret; 2468 + 2469 + *val = ret; 2470 + 2471 + return IIO_VAL_INT; 2472 + } 2473 + 2474 + return -EINVAL; 2475 + } 2476 + 2477 + #define TOSHIBA_IIO_ACCEL_CHANNEL(axis, chan) { \ 2478 + .type = IIO_ACCEL, \ 2479 + .modified = 1, \ 2480 + .channel = chan, \ 2481 + .channel2 = IIO_MOD_##axis, \ 2482 + .output = 1, \ 2483 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 2484 + } 2485 + 2486 + static const struct iio_chan_spec toshiba_iio_accel_channels[] = { 2487 + TOSHIBA_IIO_ACCEL_CHANNEL(X, AXIS_X), 2488 + TOSHIBA_IIO_ACCEL_CHANNEL(Y, AXIS_Y), 2489 + TOSHIBA_IIO_ACCEL_CHANNEL(Z, AXIS_Z), 2490 + }; 2491 + 2492 + static const struct iio_info toshiba_iio_accel_info = { 2493 + .driver_module = THIS_MODULE, 2494 + .read_raw = &toshiba_iio_accel_read_raw, 2495 + }; 2399 2496 2400 2497 /* 2401 2498 * Misc device ··· 2957 2904 2958 2905 remove_toshiba_proc_entries(dev); 2959 2906 2907 + if (dev->accelerometer_supported && dev->indio_dev) { 2908 + iio_device_unregister(dev->indio_dev); 2909 + iio_device_free(dev->indio_dev); 2910 + } 2911 + 2960 2912 if (dev->sysfs_created) 2961 2913 sysfs_remove_group(&dev->acpi_dev->dev.kobj, 2962 2914 &toshiba_attr_group); ··· 3109 3051 dev->touchpad_supported = !ret; 3110 3052 3111 3053 toshiba_accelerometer_available(dev); 3054 + if (dev->accelerometer_supported) { 3055 + dev->indio_dev = iio_device_alloc(sizeof(*dev)); 3056 + if (!dev->indio_dev) { 3057 + pr_err("Unable to allocate iio device\n"); 3058 + goto iio_error; 3059 + } 3060 + 3061 + pr_info("Registering Toshiba accelerometer iio device\n"); 3062 + 3063 + dev->indio_dev->info = &toshiba_iio_accel_info; 3064 + dev->indio_dev->name = "Toshiba accelerometer"; 3065 + dev->indio_dev->dev.parent = &acpi_dev->dev; 3066 + dev->indio_dev->modes = INDIO_DIRECT_MODE; 3067 + dev->indio_dev->channels = toshiba_iio_accel_channels; 3068 + dev->indio_dev->num_channels = 3069 + ARRAY_SIZE(toshiba_iio_accel_channels); 3070 + 3071 + ret = iio_device_register(dev->indio_dev); 3072 + if (ret < 0) { 3073 + pr_err("Unable to register iio device\n"); 3074 + iio_device_free(dev->indio_dev); 3075 + } 3076 + } 3077 + iio_error: 3112 3078 3113 3079 toshiba_usb_sleep_charge_available(dev); 3114 3080