@@ -28,6 +28,12 @@ struct macsmc_input {
2828 struct input_dev * input ;
2929 struct notifier_block nb ;
3030 bool wakeup_mode ;
31+ int ignore_btn_count ;
32+ struct delayed_work lid_work ;
33+ u8 pending_lid_state ;
34+ u8 debounce_lid_state ;
35+ int debounce_count ;
36+ bool have_lid ;
3137};
3238
3339#define SMC_EV_BTN 0x7201
@@ -46,11 +52,21 @@ static void macsmc_input_event_button(struct macsmc_input *smcin, unsigned long
4652 switch (button ) {
4753 case BTN_POWER :
4854 case BTN_TOUCHID :
55+ /*
56+ * The SMC fires a spurious BTN_TOUCHID press+release ~1ms
57+ * after entering s2idle. Skip those first 2 events, then
58+ * let real presses through normally.
59+ */
60+ if (smcin -> wakeup_mode && smcin -> ignore_btn_count > 0 ) {
61+ smcin -> ignore_btn_count -- ;
62+ return ;
63+ }
64+
4965 pm_wakeup_dev_event (smcin -> dev , 0 , (smcin -> wakeup_mode && state ));
5066 /*
5167 * Suppress KEY_POWER reports when suspended to avoid powering down
5268 * immediately after waking from s2idle.
53- * * /
69+ */
5470 if (smcin -> wakeup_mode )
5571 return ;
5672
@@ -79,14 +95,75 @@ static void macsmc_input_event_button(struct macsmc_input *smcin, unsigned long
7995 }
8096}
8197
98+ static void macsmc_input_lid_work (struct work_struct * work )
99+ {
100+ struct macsmc_input * smcin = container_of (work , struct macsmc_input , lid_work .work );
101+ u8 val ;
102+ int ret ;
103+
104+ ret = apple_smc_read_u8 (smcin -> smc , SMC_KEY (MSLD ), & val );
105+ if (ret ) {
106+ dev_warn_once (smcin -> dev , "MSLD read failed: %d\n" , ret );
107+ goto resched ;
108+ }
109+
110+ /*
111+ * Debounce: DP disconnect can cause MSLD to bounce briefly.
112+ * Require 2 consecutive polls with the same changed value
113+ * before reporting a lid state change.
114+ */
115+ if (val != smcin -> debounce_lid_state ) {
116+ smcin -> debounce_lid_state = val ;
117+ smcin -> debounce_count = 1 ;
118+ } else {
119+ smcin -> debounce_count ++ ;
120+ }
121+
122+ if (smcin -> debounce_lid_state != smcin -> pending_lid_state &&
123+ smcin -> debounce_count >= 2 ) {
124+ dev_info (smcin -> dev , "lid state changed: %d -> %d\n" ,
125+ smcin -> pending_lid_state , smcin -> debounce_lid_state );
126+ smcin -> pending_lid_state = smcin -> debounce_lid_state ;
127+ input_report_switch (smcin -> input , SW_LID , smcin -> pending_lid_state );
128+ input_sync (smcin -> input );
129+ }
130+
131+ resched :
132+ schedule_delayed_work (& smcin -> lid_work , msecs_to_jiffies (1000 ));
133+ }
134+
82135static void macsmc_input_event_lid (struct macsmc_input * smcin , unsigned long event )
83136{
84- u8 lid_state = !!((event >> 8 ) & 0xff );
137+ /*
138+ * SMC lid events (0x7203) are not reliably delivered via RTKit
139+ * notifications on all machines. Lid state is polled via the
140+ * MSLD key in lid_work instead.
141+ */
142+ }
143+
144+ static ssize_t msld_state_show (struct device * dev ,
145+ struct device_attribute * attr , char * buf )
146+ {
147+ struct macsmc_input * smcin = dev_get_drvdata (dev );
148+ u8 val ;
149+ int ret ;
85150
86- pm_wakeup_dev_event (smcin -> dev , 0 , (smcin -> wakeup_mode && !lid_state ));
87- input_report_switch (smcin -> input , SW_LID , lid_state );
88- input_sync (smcin -> input );
151+ if (!smcin -> have_lid )
152+ return sysfs_emit (buf , "unsupported\n" );
153+
154+ ret = apple_smc_read_u8 (smcin -> smc , SMC_KEY (MSLD ), & val );
155+ if (ret )
156+ return sysfs_emit (buf , "error %d\n" , ret );
157+
158+ return sysfs_emit (buf , "%d\n" , val );
89159}
160+ static DEVICE_ATTR_RO (msld_state );
161+
162+ static struct attribute * macsmc_input_attrs [] = {
163+ & dev_attr_msld_state .attr ,
164+ NULL ,
165+ };
166+ ATTRIBUTE_GROUPS (macsmc_input );
90167
91168static int macsmc_input_event (struct notifier_block * nb , unsigned long event , void * data )
92169{
@@ -125,7 +202,9 @@ static int macsmc_input_probe(struct platform_device *pdev)
125202
126203 smcin -> dev = & pdev -> dev ;
127204 smcin -> smc = smc ;
205+ smcin -> have_lid = have_lid ;
128206 platform_set_drvdata (pdev , smcin );
207+ INIT_DELAYED_WORK (& smcin -> lid_work , macsmc_input_lid_work );
129208
130209 smcin -> input = devm_input_allocate_device (& pdev -> dev );
131210 if (!smcin -> input )
@@ -143,10 +222,14 @@ static int macsmc_input_probe(struct platform_device *pdev)
143222 u8 val ;
144223
145224 error = apple_smc_read_u8 (smc , SMC_KEY (MSLD ), & val );
146- if (error < 0 )
225+ if (error < 0 ) {
147226 dev_warn (& pdev -> dev , "Failed to read initial lid state\n" );
148- else
227+ } else {
228+ smcin -> pending_lid_state = val ;
229+ smcin -> debounce_lid_state = val ;
230+ smcin -> debounce_count = 2 ;
149231 input_report_switch (smcin -> input , SW_LID , val );
232+ }
150233 }
151234
152235 if (have_power ) {
@@ -172,22 +255,39 @@ static int macsmc_input_probe(struct platform_device *pdev)
172255
173256 device_init_wakeup (& pdev -> dev , true);
174257
258+ if (have_lid )
259+ schedule_delayed_work (& smcin -> lid_work , msecs_to_jiffies (1000 ));
260+
175261 return 0 ;
176262}
177263
264+ static void macsmc_input_remove (struct platform_device * pdev )
265+ {
266+ struct macsmc_input * smcin = platform_get_drvdata (pdev );
267+ struct apple_smc * smc = smcin -> smc ;
268+
269+ cancel_delayed_work_sync (& smcin -> lid_work );
270+ blocking_notifier_chain_unregister (& smc -> event_handlers , & smcin -> nb );
271+ }
272+
178273static int macsmc_input_pm_prepare (struct device * dev )
179274{
180275 struct macsmc_input * smcin = dev_get_drvdata (dev );
181276
182277 smcin -> wakeup_mode = true;
278+ smcin -> ignore_btn_count = 2 ;
183279 return 0 ;
184280}
185281
186282static void macsmc_input_pm_complete (struct device * dev )
187283{
188284 struct macsmc_input * smcin = dev_get_drvdata (dev );
189285
286+ cancel_delayed_work_sync (& smcin -> lid_work );
190287 smcin -> wakeup_mode = false;
288+ smcin -> ignore_btn_count = 0 ;
289+ if (smcin -> have_lid )
290+ schedule_delayed_work (& smcin -> lid_work , msecs_to_jiffies (1000 ));
191291}
192292
193293static const struct dev_pm_ops macsmc_input_pm_ops = {
@@ -199,8 +299,10 @@ static struct platform_driver macsmc_input_driver = {
199299 .driver = {
200300 .name = "macsmc-input" ,
201301 .pm = & macsmc_input_pm_ops ,
302+ .dev_groups = macsmc_input_groups ,
202303 },
203304 .probe = macsmc_input_probe ,
305+ .remove = macsmc_input_remove ,
204306};
205307module_platform_driver (macsmc_input_driver );
206308
0 commit comments