Lines Matching +full:device +full:- +full:handle

1 // SPDX-License-Identifier: GPL-2.0+
12 #include <linux/input/sparse-keymap.h>
21 TABLET_SW_AUTO = -1,
31 "If you need this please report this to: platform-driver-x86@vger.kernel.org");
36 "Enable SW_TABLET_MODE reporting -1:auto 0:off 1:at-first-event 2:at-probe. "
37 "If you need this please report this to: platform-driver-x86@vger.kernel.org");
62 /* 1: LSuper (Page 0x07, usage 0xE3) -- unclear what to do */
63 /* 2: Toggle SW_ROTATE_LOCK -- easy to implement if seen in wild */
72 /* 13 has two different meanings in the spec -- ignore it. */
80 /* 27: wake -- needs special handling */
139 * Some convertible use the intel-hid ACPI interface to report SW_TABLET_MODE,
148 DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 15-df0xxx"),
191 #define HID_EVENT_FILTER_UUID "eeec56b3-4442-408f-a792-4edd4d758054"
223 static bool intel_hid_execute_method(acpi_handle handle, in intel_hid_execute_method() argument
248 obj = acpi_evaluate_dsm(handle, &intel_dsm_guid, 1, fn_index, &argv4); in intel_hid_execute_method()
250 acpi_handle_debug(handle, "Exec DSM Fn code: %d[%s] success\n", in intel_hid_execute_method()
257 status = acpi_execute_simple_method(handle, method_name, arg); in intel_hid_execute_method()
264 static bool intel_hid_evaluate_method(acpi_handle handle, in intel_hid_evaluate_method() argument
281 obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid, in intel_hid_evaluate_method()
285 *result = obj->integer.value; in intel_hid_evaluate_method()
286 acpi_handle_debug(handle, in intel_hid_evaluate_method()
294 status = acpi_evaluate_integer(handle, method_name, NULL, result); in intel_hid_evaluate_method()
301 static void intel_hid_init_dsm(acpi_handle handle) in intel_hid_init_dsm() argument
307 obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid, 1, 0, NULL, in intel_hid_init_dsm()
310 switch (obj->buffer.length) { in intel_hid_init_dsm()
313 intel_hid_dsm_fn_mask = *(u16 *)obj->buffer.pointer; in intel_hid_init_dsm()
316 intel_hid_dsm_fn_mask = *obj->buffer.pointer; in intel_hid_init_dsm()
319 acpi_handle_warn(handle, "intel_hid_dsm_fn_mask length is zero\n"); in intel_hid_init_dsm()
326 acpi_handle_debug(handle, "intel_hid_dsm_fn_mask = %llx\n", in intel_hid_init_dsm()
330 static int intel_hid_set_enable(struct device *device, bool enable) in intel_hid_set_enable() argument
332 acpi_handle handle = ACPI_HANDLE(device); in intel_hid_set_enable() local
334 /* Enable|disable features - power button is always enabled */ in intel_hid_set_enable()
335 if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN, enable)) { in intel_hid_set_enable()
336 dev_warn(device, "failed to %s hotkeys\n", str_enable_disable(enable)); in intel_hid_set_enable()
337 return -EIO; in intel_hid_set_enable()
343 static void intel_button_array_enable(struct device *device, bool enable) in intel_button_array_enable() argument
345 struct intel_hid_priv *priv = dev_get_drvdata(device); in intel_button_array_enable()
346 acpi_handle handle = ACPI_HANDLE(device); in intel_button_array_enable() local
350 if (!priv->array) in intel_button_array_enable()
354 status = acpi_evaluate_integer(handle, "BTNC", NULL, &button_cap); in intel_button_array_enable()
356 dev_warn(device, "failed to get button capability\n"); in intel_button_array_enable()
360 /* Enable|disable features - power button is always enabled */ in intel_button_array_enable()
361 if (!intel_hid_execute_method(handle, INTEL_HID_DSM_BTNE_FN, in intel_button_array_enable()
363 dev_warn(device, "failed to set button capability\n"); in intel_button_array_enable()
366 static int intel_hid_pm_prepare(struct device *device) in intel_hid_pm_prepare() argument
368 if (device_may_wakeup(device)) { in intel_hid_pm_prepare()
369 struct intel_hid_priv *priv = dev_get_drvdata(device); in intel_hid_pm_prepare()
371 priv->wakeup_mode = true; in intel_hid_pm_prepare()
376 static void intel_hid_pm_complete(struct device *device) in intel_hid_pm_complete() argument
378 struct intel_hid_priv *priv = dev_get_drvdata(device); in intel_hid_pm_complete()
380 priv->wakeup_mode = false; in intel_hid_pm_complete()
383 static int intel_hid_pl_suspend_handler(struct device *device) in intel_hid_pl_suspend_handler() argument
385 intel_button_array_enable(device, false); in intel_hid_pl_suspend_handler()
388 intel_hid_set_enable(device, false); in intel_hid_pl_suspend_handler()
393 static int intel_hid_pl_resume_handler(struct device *device) in intel_hid_pl_resume_handler() argument
395 intel_hid_pm_complete(device); in intel_hid_pl_resume_handler()
398 intel_hid_set_enable(device, true); in intel_hid_pl_resume_handler()
400 intel_button_array_enable(device, true); in intel_hid_pl_resume_handler()
414 static int intel_hid_input_setup(struct platform_device *device) in intel_hid_input_setup() argument
416 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); in intel_hid_input_setup()
419 priv->input_dev = devm_input_allocate_device(&device->dev); in intel_hid_input_setup()
420 if (!priv->input_dev) in intel_hid_input_setup()
421 return -ENOMEM; in intel_hid_input_setup()
423 ret = sparse_keymap_setup(priv->input_dev, intel_hid_keymap, NULL); in intel_hid_input_setup()
427 priv->input_dev->name = "Intel HID events"; in intel_hid_input_setup()
428 priv->input_dev->id.bustype = BUS_HOST; in intel_hid_input_setup()
430 return input_register_device(priv->input_dev); in intel_hid_input_setup()
433 static int intel_button_array_input_setup(struct platform_device *device) in intel_button_array_input_setup() argument
435 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); in intel_button_array_input_setup()
438 /* Setup input device for 5 button array */ in intel_button_array_input_setup()
439 priv->array = devm_input_allocate_device(&device->dev); in intel_button_array_input_setup()
440 if (!priv->array) in intel_button_array_input_setup()
441 return -ENOMEM; in intel_button_array_input_setup()
443 ret = sparse_keymap_setup(priv->array, intel_array_keymap, NULL); in intel_button_array_input_setup()
447 priv->array->name = "Intel HID 5 button array"; in intel_button_array_input_setup()
448 priv->array->id.bustype = BUS_HOST; in intel_button_array_input_setup()
450 return input_register_device(priv->array); in intel_button_array_input_setup()
453 static int intel_hid_switches_setup(struct platform_device *device) in intel_hid_switches_setup() argument
455 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); in intel_hid_switches_setup()
457 /* Setup input device for switches */ in intel_hid_switches_setup()
458 priv->switches = devm_input_allocate_device(&device->dev); in intel_hid_switches_setup()
459 if (!priv->switches) in intel_hid_switches_setup()
460 return -ENOMEM; in intel_hid_switches_setup()
462 __set_bit(EV_SW, priv->switches->evbit); in intel_hid_switches_setup()
463 __set_bit(SW_TABLET_MODE, priv->switches->swbit); in intel_hid_switches_setup()
465 priv->switches->name = "Intel HID switches"; in intel_hid_switches_setup()
466 priv->switches->id.bustype = BUS_HOST; in intel_hid_switches_setup()
467 return input_register_device(priv->switches); in intel_hid_switches_setup()
470 static void report_tablet_mode_state(struct platform_device *device) in report_tablet_mode_state() argument
472 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); in report_tablet_mode_state()
473 acpi_handle handle = ACPI_HANDLE(&device->dev); in report_tablet_mode_state() local
477 if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_VGBS_FN, &vgbs)) in report_tablet_mode_state()
481 input_report_switch(priv->switches, SW_TABLET_MODE, m); in report_tablet_mode_state()
482 input_sync(priv->switches); in report_tablet_mode_state()
504 static void notify_handler(acpi_handle handle, u32 event, void *context) in notify_handler() argument
506 struct platform_device *device = context; in notify_handler() local
507 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); in notify_handler()
517 if (!priv->switches && enable_sw_tablet_mode == TABLET_SW_AT_EVENT && in notify_handler()
519 dev_info(&device->dev, "switch event received, enable switches supports\n"); in notify_handler()
520 err = intel_hid_switches_setup(device); in notify_handler()
525 if (priv->wakeup_mode) { in notify_handler()
527 * Needed for wakeup from suspend-to-idle to work on some in notify_handler()
528 * platforms that don't expose the 5-button array, but still in notify_handler()
530 * device object on power button actions while suspended. in notify_handler()
536 * Some devices send (duplicate) tablet-mode events when moved in notify_handler()
543 report_tablet_mode_event(priv->switches, event); in notify_handler()
547 /* Wake up on 5-button array events only. */ in notify_handler()
548 if (event == 0xc0 || !priv->array) in notify_handler()
551 ke = sparse_keymap_entry_from_scancode(priv->array, event); in notify_handler()
553 dev_info(&device->dev, "unknown event 0x%x\n", event); in notify_handler()
557 if (ke->type == KE_IGNORE) in notify_handler()
561 pm_wakeup_hard_event(&device->dev); in notify_handler()
568 * the 5-button array, but still send notifies with power button in notify_handler()
569 * event code to this device object on power button actions. in notify_handler()
573 if (!priv->array) { in notify_handler()
575 input_report_key(priv->input_dev, KEY_POWER, 1); in notify_handler()
576 input_sync(priv->input_dev); in notify_handler()
581 input_report_key(priv->input_dev, KEY_POWER, 0); in notify_handler()
582 input_sync(priv->input_dev); in notify_handler()
587 if (report_tablet_mode_event(priv->switches, event)) in notify_handler()
592 if (!priv->array || in notify_handler()
593 !sparse_keymap_report_event(priv->array, event, 1, true)) in notify_handler()
594 dev_dbg(&device->dev, "unknown event 0x%x\n", event); in notify_handler()
598 if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDEM_FN, in notify_handler()
600 dev_warn(&device->dev, "failed to get event index\n"); in notify_handler()
604 if (!sparse_keymap_report_event(priv->input_dev, ev_index, 1, true)) in notify_handler()
605 dev_dbg(&device->dev, "unknown event index 0x%llx\n", in notify_handler()
609 static bool button_array_present(struct platform_device *device) in button_array_present() argument
611 acpi_handle handle = ACPI_HANDLE(&device->dev); in button_array_present() local
614 if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V2_FN, in button_array_present()
621 if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V1_FN, in button_array_present()
633 static int intel_hid_probe(struct platform_device *device) in intel_hid_probe() argument
635 acpi_handle handle = ACPI_HANDLE(&device->dev); in intel_hid_probe() local
641 intel_hid_init_dsm(handle); in intel_hid_probe()
643 if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDMM_FN, &mode)) { in intel_hid_probe()
644 dev_warn(&device->dev, "failed to read mode\n"); in intel_hid_probe()
645 return -ENODEV; in intel_hid_probe()
654 dev_info(&device->dev, "platform is not in simple mode\n"); in intel_hid_probe()
655 return -ENODEV; in intel_hid_probe()
658 priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL); in intel_hid_probe()
660 return -ENOMEM; in intel_hid_probe()
661 dev_set_drvdata(&device->dev, priv); in intel_hid_probe()
673 err = intel_hid_input_setup(device); in intel_hid_probe()
680 if (button_array_present(device)) { in intel_hid_probe()
681 dev_info(&device->dev, "platform supports 5 button array\n"); in intel_hid_probe()
682 err = intel_button_array_input_setup(device); in intel_hid_probe()
689 dev_info(&device->dev, "platform supports switches\n"); in intel_hid_probe()
690 err = intel_hid_switches_setup(device); in intel_hid_probe()
694 report_tablet_mode_state(device); in intel_hid_probe()
697 status = acpi_install_notify_handler(handle, in intel_hid_probe()
700 device); in intel_hid_probe()
702 return -EBUSY; in intel_hid_probe()
704 err = intel_hid_set_enable(&device->dev, true); in intel_hid_probe()
708 intel_button_array_enable(&device->dev, true); in intel_hid_probe()
715 if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy)) in intel_hid_probe()
716 dev_warn(&device->dev, "failed to enable HID power button\n"); in intel_hid_probe()
718 device_init_wakeup(&device->dev, true); in intel_hid_probe()
728 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); in intel_hid_probe()
733 static void intel_hid_remove(struct platform_device *device) in intel_hid_remove() argument
735 acpi_handle handle = ACPI_HANDLE(&device->dev); in intel_hid_remove() local
737 device_init_wakeup(&device->dev, false); in intel_hid_remove()
738 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); in intel_hid_remove()
739 intel_hid_set_enable(&device->dev, false); in intel_hid_remove()
740 intel_button_array_enable(&device->dev, false); in intel_hid_remove()
745 .name = "intel-hid",
754 * Unfortunately, some laptops provide a _HID="INT33D5" device with
756 * ACPI node, so no platform device will be created. The pnpacpi
757 * driver rejects this device in subsequent processing, so no physical
760 * As a workaround until the ACPI core figures out how to handle
761 * this corner case, manually ask the ACPI platform device code to
765 check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) in check_acpi_dev() argument
768 struct acpi_device *dev = acpi_fetch_acpi_dev(handle); in check_acpi_dev()
772 dev_info(&dev->dev, in check_acpi_dev()
773 "intel-hid: created platform device\n"); in check_acpi_dev()