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