^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * button.c - ACPI Button Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define pr_fmt(fmt) "ACPI: button: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <acpi/button.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PREFIX "ACPI: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define ACPI_BUTTON_CLASS "button"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define ACPI_BUTTON_FILE_STATE "state"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define ACPI_BUTTON_TYPE_UNKNOWN 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define ACPI_BUTTON_NOTIFY_STATUS 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define ACPI_BUTTON_SUBCLASS_POWER "power"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define ACPI_BUTTON_TYPE_POWER 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define ACPI_BUTTON_TYPE_SLEEP 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define ACPI_BUTTON_SUBCLASS_LID "lid"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define ACPI_BUTTON_TYPE_LID 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ACPI_BUTTON_LID_INIT_IGNORE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ACPI_BUTTON_LID_INIT_OPEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ACPI_BUTTON_LID_INIT_METHOD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ACPI_BUTTON_LID_INIT_DISABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static const char * const lid_init_state_str[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) [ACPI_BUTTON_LID_INIT_IGNORE] = "ignore",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) [ACPI_BUTTON_LID_INIT_OPEN] = "open",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) [ACPI_BUTTON_LID_INIT_METHOD] = "method",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [ACPI_BUTTON_LID_INIT_DISABLED] = "disabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define _COMPONENT ACPI_BUTTON_COMPONENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ACPI_MODULE_NAME("button");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) MODULE_AUTHOR("Paul Diefenbaugh");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) MODULE_DESCRIPTION("ACPI Button Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const struct acpi_device_id button_device_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {ACPI_BUTTON_HID_LID, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {ACPI_BUTTON_HID_SLEEP, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {ACPI_BUTTON_HID_SLEEPF, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {ACPI_BUTTON_HID_POWER, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {ACPI_BUTTON_HID_POWERF, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {"", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MODULE_DEVICE_TABLE(acpi, button_device_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Please keep this list sorted alphabetically by vendor and model */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const struct dmi_system_id dmi_lid_quirks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* GP-electronic T701, _LID method points to a floating GPIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Medion Akoya E2215T, notification of the LID device only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * happens on close, not on open and _LID always returns closed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) DMI_MATCH(DMI_PRODUCT_NAME, "E2215T"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Medion Akoya E2228T, notification of the LID device only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * happens on close, not on open and _LID always returns closed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) DMI_MATCH(DMI_PRODUCT_NAME, "E2228T"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Razer Blade Stealth 13 late 2019, notification of the LID device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * only happens on close, not on open and _LID always returns closed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) DMI_MATCH(DMI_PRODUCT_NAME, "Razer Blade Stealth 13 Late 2019"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int acpi_button_add(struct acpi_device *device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int acpi_button_remove(struct acpi_device *device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static void acpi_button_notify(struct acpi_device *device, u32 event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int acpi_button_suspend(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static int acpi_button_resume(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define acpi_button_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define acpi_button_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static struct acpi_driver acpi_button_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .name = "button",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .class = ACPI_BUTTON_CLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .ids = button_device_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .add = acpi_button_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .remove = acpi_button_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .notify = acpi_button_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .drv.pm = &acpi_button_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct acpi_button {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct input_dev *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) char phys[32]; /* for input device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned long pushed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int last_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ktime_t last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bool suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) bool lid_state_initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static struct acpi_device *lid_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static long lid_init_state = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static unsigned long lid_report_interval __read_mostly = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) module_param(lid_report_interval, ulong, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) FS Interface (/proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) -------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static struct proc_dir_entry *acpi_button_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static struct proc_dir_entry *acpi_lid_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int acpi_lid_evaluate_state(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned long long lid_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (ACPI_FAILURE(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return lid_state ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static int acpi_lid_notify_state(struct acpi_device *device, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ktime_t next_report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) bool do_update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * In lid_init_state=ignore mode, if user opens/closes lid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * frequently with "open" missing, and "last_time" is also updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * frequently, "close" cannot be delivered to the userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * So "last_time" is only updated after a timeout or an actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * switch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) button->last_state != !!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) do_update = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) do_update = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) next_report = ktime_add(button->last_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ms_to_ktime(lid_report_interval));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (button->last_state == !!state &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ktime_after(ktime_get(), next_report)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* Complain the buggy firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pr_warn_once("The lid device is not compliant to SW_LID.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Send the unreliable complement switch event:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * On most platforms, the lid device is reliable. However
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * there are exceptions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * 1. Platforms returning initial lid state as "close" by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * default after booting/resuming:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * https://bugzilla.kernel.org/show_bug.cgi?id=89211
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * https://bugzilla.kernel.org/show_bug.cgi?id=106151
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * 2. Platforms never reporting "open" events:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * https://bugzilla.kernel.org/show_bug.cgi?id=106941
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * On these buggy platforms, the usage model of the ACPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * lid device actually is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * 1. The initial returning value of _LID may not be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * reliable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * 2. The open event may not be reliable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * 3. The close event is reliable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * But SW_LID is typed as input switch event, the input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * layer checks if the event is redundant. Hence if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * state is not switched, the userspace cannot see this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * platform triggered reliable event. By inserting a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * complement switch event, it then is guaranteed that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * platform triggered reliable one can always be seen by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * the userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) do_update = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Do generate complement switch event for "close"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * as "close" is reliable and wrong "open" won't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * trigger unexpected behaviors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * Do not generate complement switch event for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * "open" as "open" is not reliable and wrong
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * "close" will trigger unexpected behaviors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) input_report_switch(button->input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) SW_LID, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) input_sync(button->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Send the platform triggered reliable event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (do_update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) acpi_handle_debug(device->handle, "ACPI LID %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) state ? "open" : "closed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) input_report_switch(button->input, SW_LID, !state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) input_sync(button->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) button->last_state = !!state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) button->last_time = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int __maybe_unused acpi_button_state_seq_show(struct seq_file *seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) void *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct acpi_device *device = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) state = acpi_lid_evaluate_state(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) seq_printf(seq, "state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) state < 0 ? "unsupported" : (state ? "open" : "closed"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int acpi_button_add_fs(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct proc_dir_entry *entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* procfs I/F for ACPI lid device only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (button->type != ACPI_BUTTON_TYPE_LID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (acpi_button_dir || acpi_lid_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) printk(KERN_ERR PREFIX "More than one Lid device found!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* create /proc/acpi/button */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!acpi_button_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /* create /proc/acpi/button/lid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!acpi_lid_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) goto remove_button_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* create /proc/acpi/button/lid/LID/ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!acpi_device_dir(device)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) goto remove_lid_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* create /proc/acpi/button/lid/LID/state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) entry = proc_create_single_data(ACPI_BUTTON_FILE_STATE, S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) acpi_device_dir(device), acpi_button_state_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto remove_dev_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) remove_dev_dir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) remove_proc_entry(acpi_device_bid(device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) acpi_lid_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) acpi_device_dir(device) = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) remove_lid_dir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) acpi_lid_dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) remove_button_dir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) acpi_button_dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static int acpi_button_remove_fs(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (button->type != ACPI_BUTTON_TYPE_LID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) remove_proc_entry(ACPI_BUTTON_FILE_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) acpi_device_dir(device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) remove_proc_entry(acpi_device_bid(device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) acpi_lid_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) acpi_device_dir(device) = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) acpi_lid_dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) acpi_button_dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) Driver Interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) -------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int acpi_lid_open(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (!lid_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return acpi_lid_evaluate_state(lid_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) EXPORT_SYMBOL(acpi_lid_open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int acpi_lid_update_state(struct acpi_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) bool signal_wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) state = acpi_lid_evaluate_state(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (state < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (state && signal_wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) acpi_pm_wakeup_event(&device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return acpi_lid_notify_state(device, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static void acpi_lid_initialize_state(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) switch (lid_init_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case ACPI_BUTTON_LID_INIT_OPEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) (void)acpi_lid_notify_state(device, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) case ACPI_BUTTON_LID_INIT_METHOD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) (void)acpi_lid_update_state(device, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) case ACPI_BUTTON_LID_INIT_IGNORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) button->lid_state_initialized = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static void acpi_button_notify(struct acpi_device *device, u32 event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct input_dev *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) case ACPI_FIXED_HARDWARE_EVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) event = ACPI_BUTTON_NOTIFY_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) case ACPI_BUTTON_NOTIFY_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) input = button->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (button->type == ACPI_BUTTON_TYPE_LID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (button->lid_state_initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) acpi_lid_update_state(device, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int keycode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) acpi_pm_wakeup_event(&device->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (button->suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) keycode = test_bit(KEY_SLEEP, input->keybit) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) KEY_SLEEP : KEY_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) input_report_key(input, keycode, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) input_sync(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) input_report_key(input, keycode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) input_sync(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) acpi_bus_generate_netlink_event(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) device->pnp.device_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dev_name(&device->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) event, ++button->pushed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) "Unsupported event [0x%x]\n", event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static int acpi_button_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct acpi_device *device = to_acpi_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) button->suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static int acpi_button_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct acpi_device *device = to_acpi_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) button->suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (button->type == ACPI_BUTTON_TYPE_LID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) button->last_state = !!acpi_lid_evaluate_state(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) button->last_time = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) acpi_lid_initialize_state(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int acpi_lid_input_open(struct input_dev *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct acpi_device *device = input_get_drvdata(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) button->last_state = !!acpi_lid_evaluate_state(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) button->last_time = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) acpi_lid_initialize_state(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static int acpi_button_add(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct acpi_button *button;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct input_dev *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) const char *hid = acpi_device_hid(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) char *name, *class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!strcmp(hid, ACPI_BUTTON_HID_LID) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (!button)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) device->driver_data = button;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) button->input = input = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (!input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) goto err_free_button;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) name = acpi_device_name(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) class = acpi_device_class(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) !strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) button->type = ACPI_BUTTON_TYPE_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) sprintf(class, "%s/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) button->type = ACPI_BUTTON_TYPE_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) sprintf(class, "%s/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) button->type = ACPI_BUTTON_TYPE_LID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) sprintf(class, "%s/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) input->open = acpi_lid_input_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) goto err_free_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) error = acpi_button_add_fs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto err_free_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) input->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) input->phys = button->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) input->id.bustype = BUS_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) input->id.product = button->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) input->dev.parent = &device->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) switch (button->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) case ACPI_BUTTON_TYPE_POWER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) input_set_capability(input, EV_KEY, KEY_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) case ACPI_BUTTON_TYPE_SLEEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) input_set_capability(input, EV_KEY, KEY_SLEEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case ACPI_BUTTON_TYPE_LID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) input_set_capability(input, EV_SW, SW_LID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) input_set_drvdata(input, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) error = input_register_device(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto err_remove_fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (button->type == ACPI_BUTTON_TYPE_LID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * This assumes there's only one lid device, or if there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * more we only care about the last one...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) lid_device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) device_init_wakeup(&device->dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) err_remove_fs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) acpi_button_remove_fs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) err_free_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) input_free_device(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) err_free_button:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) kfree(button);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int acpi_button_remove(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct acpi_button *button = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) acpi_button_remove_fs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) input_unregister_device(button->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) kfree(button);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int param_set_lid_init_state(const char *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) i = sysfs_match_string(lid_init_state_str, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) lid_init_state = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) pr_info("Initial lid state set to '%s'\n", lid_init_state_str[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) static int param_get_lid_init_state(char *buf, const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) int i, c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) for (i = 0; i < ARRAY_SIZE(lid_init_state_str); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (i == lid_init_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) c += sprintf(buf + c, "[%s] ", lid_init_state_str[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) c += sprintf(buf + c, "%s ", lid_init_state_str[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) buf[c - 1] = '\n'; /* Replace the final space with a newline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) module_param_call(lid_init_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) param_set_lid_init_state, param_get_lid_init_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) NULL, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static int acpi_button_register_driver(struct acpi_driver *driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) const struct dmi_system_id *dmi_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (lid_init_state == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) dmi_id = dmi_first_match(dmi_lid_quirks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (dmi_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) lid_init_state = (long)dmi_id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * Modules such as nouveau.ko and i915.ko have a link time dependency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * on acpi_lid_open(), and would therefore not be loadable on ACPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * capable kernels booted in non-ACPI mode if the return value of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * acpi_bus_register_driver() is returned from here with ACPI disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * when this driver is built as a module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (acpi_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return acpi_bus_register_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static void acpi_button_unregister_driver(struct acpi_driver *driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!acpi_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) acpi_bus_unregister_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) module_driver(acpi_button_driver, acpi_button_register_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) acpi_button_unregister_driver);