44
44
#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
45
45
#define ACPI_BUTTON_TYPE_LID 0x05
46
46
47
- #define ACPI_BUTTON_LID_INIT_IGNORE 0x00
48
- #define ACPI_BUTTON_LID_INIT_OPEN 0x01
49
- #define ACPI_BUTTON_LID_INIT_METHOD 0x02
47
+ enum {
48
+ ACPI_BUTTON_LID_INIT_IGNORE ,
49
+ ACPI_BUTTON_LID_INIT_OPEN ,
50
+ ACPI_BUTTON_LID_INIT_METHOD ,
51
+ ACPI_BUTTON_LID_INIT_DISABLED ,
52
+ };
53
+
54
+ static const char * const lid_init_state_str [] = {
55
+ [ACPI_BUTTON_LID_INIT_IGNORE ] = "ignore" ,
56
+ [ACPI_BUTTON_LID_INIT_OPEN ] = "open" ,
57
+ [ACPI_BUTTON_LID_INIT_METHOD ] = "method" ,
58
+ [ACPI_BUTTON_LID_INIT_DISABLED ] = "disabled" ,
59
+ };
50
60
51
61
#define _COMPONENT ACPI_BUTTON_COMPONENT
52
62
ACPI_MODULE_NAME ("button" );
@@ -65,18 +75,39 @@ static const struct acpi_device_id button_device_ids[] = {
65
75
};
66
76
MODULE_DEVICE_TABLE (acpi , button_device_ids );
67
77
68
- /*
69
- * Some devices which don't even have a lid in anyway have a broken _LID
70
- * method (e.g. pointing to a floating gpio pin) causing spurious LID events.
71
- */
72
- static const struct dmi_system_id lid_blacklst [] = {
78
+ /* Please keep this list sorted alphabetically by vendor and model */
79
+ static const struct dmi_system_id dmi_lid_quirks [] = {
80
+ {
81
+ /*
82
+ * Asus T200TA, _LID keeps reporting closed after every second
83
+ * openening of the lid. Causing immediate re-suspend after
84
+ * opening every other open. Using LID_INIT_OPEN fixes this.
85
+ */
86
+ .matches = {
87
+ DMI_MATCH (DMI_SYS_VENDOR , "ASUSTeK COMPUTER INC." ),
88
+ DMI_MATCH (DMI_PRODUCT_NAME , "T200TA" ),
89
+ },
90
+ .driver_data = (void * )(long )ACPI_BUTTON_LID_INIT_OPEN ,
91
+ },
73
92
{
74
- /* GP-electronic T701 */
93
+ /* GP-electronic T701, _LID method points to a floating GPIO */
75
94
.matches = {
76
95
DMI_MATCH (DMI_SYS_VENDOR , "Insyde" ),
77
96
DMI_MATCH (DMI_PRODUCT_NAME , "T701" ),
78
97
DMI_MATCH (DMI_BIOS_VERSION , "BYT70A.YNCHENG.WIN.007" ),
79
98
},
99
+ .driver_data = (void * )(long )ACPI_BUTTON_LID_INIT_DISABLED ,
100
+ },
101
+ {
102
+ /*
103
+ * Medion Akoya E2215T, notification of the LID device only
104
+ * happens on close, not on open and _LID always returns closed.
105
+ */
106
+ .matches = {
107
+ DMI_MATCH (DMI_SYS_VENDOR , "MEDION" ),
108
+ DMI_MATCH (DMI_PRODUCT_NAME , "E2215T MD60198" ),
109
+ },
110
+ .driver_data = (void * )(long )ACPI_BUTTON_LID_INIT_OPEN ,
80
111
},
81
112
{}
82
113
};
@@ -116,9 +147,8 @@ struct acpi_button {
116
147
bool suspended ;
117
148
};
118
149
119
- static BLOCKING_NOTIFIER_HEAD (acpi_lid_notifier );
120
150
static struct acpi_device * lid_device ;
121
- static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD ;
151
+ static long lid_init_state = -1 ;
122
152
123
153
static unsigned long lid_report_interval __read_mostly = 500 ;
124
154
module_param (lid_report_interval , ulong , 0644 );
@@ -146,7 +176,6 @@ static int acpi_lid_evaluate_state(struct acpi_device *device)
146
176
static int acpi_lid_notify_state (struct acpi_device * device , int state )
147
177
{
148
178
struct acpi_button * button = acpi_driver_data (device );
149
- int ret ;
150
179
ktime_t next_report ;
151
180
bool do_update ;
152
181
@@ -223,18 +252,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
223
252
button -> last_time = ktime_get ();
224
253
}
225
254
226
- ret = blocking_notifier_call_chain (& acpi_lid_notifier , state , device );
227
- if (ret == NOTIFY_DONE )
228
- ret = blocking_notifier_call_chain (& acpi_lid_notifier , state ,
229
- device );
230
- if (ret == NOTIFY_DONE || ret == NOTIFY_OK ) {
231
- /*
232
- * It is also regarded as success if the notifier_chain
233
- * returns NOTIFY_OK or NOTIFY_DONE.
234
- */
235
- ret = 0 ;
236
- }
237
- return ret ;
255
+ return 0 ;
238
256
}
239
257
240
258
static int __maybe_unused acpi_button_state_seq_show (struct seq_file * seq ,
@@ -331,18 +349,6 @@ static int acpi_button_remove_fs(struct acpi_device *device)
331
349
/* --------------------------------------------------------------------------
332
350
Driver Interface
333
351
-------------------------------------------------------------------------- */
334
- int acpi_lid_notifier_register (struct notifier_block * nb )
335
- {
336
- return blocking_notifier_chain_register (& acpi_lid_notifier , nb );
337
- }
338
- EXPORT_SYMBOL (acpi_lid_notifier_register );
339
-
340
- int acpi_lid_notifier_unregister (struct notifier_block * nb )
341
- {
342
- return blocking_notifier_chain_unregister (& acpi_lid_notifier , nb );
343
- }
344
- EXPORT_SYMBOL (acpi_lid_notifier_unregister );
345
-
346
352
int acpi_lid_open (void )
347
353
{
348
354
if (!lid_device )
@@ -472,7 +478,8 @@ static int acpi_button_add(struct acpi_device *device)
472
478
char * name , * class ;
473
479
int error ;
474
480
475
- if (!strcmp (hid , ACPI_BUTTON_HID_LID ) && dmi_check_system (lid_blacklst ))
481
+ if (!strcmp (hid , ACPI_BUTTON_HID_LID ) &&
482
+ lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED )
476
483
return - ENODEV ;
477
484
478
485
button = kzalloc (sizeof (struct acpi_button ), GFP_KERNEL );
@@ -578,36 +585,30 @@ static int acpi_button_remove(struct acpi_device *device)
578
585
static int param_set_lid_init_state (const char * val ,
579
586
const struct kernel_param * kp )
580
587
{
581
- int result = 0 ;
582
-
583
- if (!strncmp (val , "open" , sizeof ("open" ) - 1 )) {
584
- lid_init_state = ACPI_BUTTON_LID_INIT_OPEN ;
585
- pr_info ("Notify initial lid state as open\n" );
586
- } else if (!strncmp (val , "method" , sizeof ("method" ) - 1 )) {
587
- lid_init_state = ACPI_BUTTON_LID_INIT_METHOD ;
588
- pr_info ("Notify initial lid state with _LID return value\n" );
589
- } else if (!strncmp (val , "ignore" , sizeof ("ignore" ) - 1 )) {
590
- lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE ;
591
- pr_info ("Do not notify initial lid state\n" );
592
- } else
593
- result = - EINVAL ;
594
- return result ;
588
+ int i ;
589
+
590
+ i = sysfs_match_string (lid_init_state_str , val );
591
+ if (i < 0 )
592
+ return i ;
593
+
594
+ lid_init_state = i ;
595
+ pr_info ("Initial lid state set to '%s'\n" , lid_init_state_str [i ]);
596
+ return 0 ;
595
597
}
596
598
597
- static int param_get_lid_init_state (char * buffer ,
598
- const struct kernel_param * kp )
599
+ static int param_get_lid_init_state (char * buf , const struct kernel_param * kp )
599
600
{
600
- switch ( lid_init_state ) {
601
- case ACPI_BUTTON_LID_INIT_OPEN :
602
- return sprintf ( buffer , "open" );
603
- case ACPI_BUTTON_LID_INIT_METHOD :
604
- return sprintf (buffer , "method" );
605
- case ACPI_BUTTON_LID_INIT_IGNORE :
606
- return sprintf (buffer , "ignore" );
607
- default :
608
- return sprintf ( buffer , "invalid" );
609
- }
610
- return 0 ;
601
+ int i , c = 0 ;
602
+
603
+ for ( i = 0 ; i < ARRAY_SIZE ( lid_init_state_str ); i ++ )
604
+ if ( i == lid_init_state )
605
+ c += sprintf (buf + c , "[%s] " , lid_init_state_str [ i ] );
606
+ else
607
+ c += sprintf (buf + c , "%s " , lid_init_state_str [ i ] );
608
+
609
+ buf [ c - 1 ] = '\n' ; /* Replace the final space with a newline */
610
+
611
+ return c ;
611
612
}
612
613
613
614
module_param_call (lid_init_state ,
@@ -617,6 +618,16 @@ MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
617
618
618
619
static int acpi_button_register_driver (struct acpi_driver * driver )
619
620
{
621
+ const struct dmi_system_id * dmi_id ;
622
+
623
+ if (lid_init_state == -1 ) {
624
+ dmi_id = dmi_first_match (dmi_lid_quirks );
625
+ if (dmi_id )
626
+ lid_init_state = (long )dmi_id -> driver_data ;
627
+ else
628
+ lid_init_state = ACPI_BUTTON_LID_INIT_METHOD ;
629
+ }
630
+
620
631
/*
621
632
* Modules such as nouveau.ko and i915.ko have a link time dependency
622
633
* on acpi_lid_open(), and would therefore not be loadable on ACPI
0 commit comments