diff options
Diffstat (limited to 'arch/x86/platform/olpc/olpc-xo1-sci.c')
-rw-r--r-- | arch/x86/platform/olpc/olpc-xo1-sci.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 1d4c783d7325..04b8c73659c5 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/pm_wakeup.h> | ||
21 | #include <linux/mfd/core.h> | 22 | #include <linux/mfd/core.h> |
22 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
23 | #include <linux/suspend.h> | 24 | #include <linux/suspend.h> |
@@ -83,8 +84,12 @@ static void send_ebook_state(void) | |||
83 | return; | 84 | return; |
84 | } | 85 | } |
85 | 86 | ||
87 | if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state) | ||
88 | return; /* Nothing new to report. */ | ||
89 | |||
86 | input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state); | 90 | input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state); |
87 | input_sync(ebook_switch_idev); | 91 | input_sync(ebook_switch_idev); |
92 | pm_wakeup_event(&ebook_switch_idev->dev, 0); | ||
88 | } | 93 | } |
89 | 94 | ||
90 | static void flip_lid_inverter(void) | 95 | static void flip_lid_inverter(void) |
@@ -123,8 +128,12 @@ static void detect_lid_state(void) | |||
123 | /* Report current lid switch state through input layer */ | 128 | /* Report current lid switch state through input layer */ |
124 | static void send_lid_state(void) | 129 | static void send_lid_state(void) |
125 | { | 130 | { |
131 | if (!!test_bit(SW_LID, lid_switch_idev->sw) == !lid_open) | ||
132 | return; /* Nothing new to report. */ | ||
133 | |||
126 | input_report_switch(lid_switch_idev, SW_LID, !lid_open); | 134 | input_report_switch(lid_switch_idev, SW_LID, !lid_open); |
127 | input_sync(lid_switch_idev); | 135 | input_sync(lid_switch_idev); |
136 | pm_wakeup_event(&lid_switch_idev->dev, 0); | ||
128 | } | 137 | } |
129 | 138 | ||
130 | static ssize_t lid_wake_mode_show(struct device *dev, | 139 | static ssize_t lid_wake_mode_show(struct device *dev, |
@@ -213,11 +222,30 @@ static irqreturn_t xo1_sci_intr(int irq, void *dev_id) | |||
213 | 222 | ||
214 | dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe); | 223 | dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe); |
215 | 224 | ||
216 | if (sts & CS5536_PWRBTN_FLAG && !(sts & CS5536_WAK_FLAG)) { | 225 | if (sts & CS5536_PWRBTN_FLAG) { |
217 | input_report_key(power_button_idev, KEY_POWER, 1); | 226 | if (!(sts & CS5536_WAK_FLAG)) { |
218 | input_sync(power_button_idev); | 227 | /* Only report power button input when it was pressed |
219 | input_report_key(power_button_idev, KEY_POWER, 0); | 228 | * during regular operation (as opposed to when it |
220 | input_sync(power_button_idev); | 229 | * was used to wake the system). */ |
230 | input_report_key(power_button_idev, KEY_POWER, 1); | ||
231 | input_sync(power_button_idev); | ||
232 | input_report_key(power_button_idev, KEY_POWER, 0); | ||
233 | input_sync(power_button_idev); | ||
234 | } | ||
235 | /* Report the wakeup event in all cases. */ | ||
236 | pm_wakeup_event(&power_button_idev->dev, 0); | ||
237 | } | ||
238 | |||
239 | if ((sts & (CS5536_RTC_FLAG | CS5536_WAK_FLAG)) == | ||
240 | (CS5536_RTC_FLAG | CS5536_WAK_FLAG)) { | ||
241 | /* When the system is woken by the RTC alarm, report the | ||
242 | * event on the rtc device. */ | ||
243 | struct device *rtc = bus_find_device_by_name( | ||
244 | &platform_bus_type, NULL, "rtc_cmos"); | ||
245 | if (rtc) { | ||
246 | pm_wakeup_event(rtc, 0); | ||
247 | put_device(rtc); | ||
248 | } | ||
221 | } | 249 | } |
222 | 250 | ||
223 | if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */ | 251 | if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */ |
@@ -310,9 +338,10 @@ static int __devinit setup_sci_interrupt(struct platform_device *pdev) | |||
310 | outb(lo, CS5536_PIC_INT_SEL2); | 338 | outb(lo, CS5536_PIC_INT_SEL2); |
311 | } | 339 | } |
312 | 340 | ||
313 | /* Enable SCI from power button, and clear pending interrupts */ | 341 | /* Enable interesting SCI events, and clear pending interrupts */ |
314 | sts = inl(acpi_base + CS5536_PM1_STS); | 342 | sts = inl(acpi_base + CS5536_PM1_STS); |
315 | outl((CS5536_PM_PWRBTN << 16) | 0xffff, acpi_base + CS5536_PM1_STS); | 343 | outl(((CS5536_PM_PWRBTN | CS5536_PM_RTC) << 16) | 0xffff, |
344 | acpi_base + CS5536_PM1_STS); | ||
316 | 345 | ||
317 | r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev); | 346 | r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev); |
318 | if (r) | 347 | if (r) |