aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-09-16 04:06:43 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-09-18 02:23:58 -0400
commitffd0db97196c1057f09c2ab42dd5b30e94e511d9 (patch)
tree5ac8654257d52612227c6eab1b32e13a71b9c54d /drivers/input
parent181d683d752c432635eda0f182ee71548c1f1820 (diff)
Input: add generic suspend and resume for input devices
Automatically turn off leds and sound effects as part of suspend process and restore led state, sounds and repeat rate at resume. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/input.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 7c237e6ac711..b8ed4294fccd 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/types.h>
14#include <linux/input.h> 15#include <linux/input.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/random.h> 17#include <linux/random.h>
@@ -514,7 +515,7 @@ static void input_disconnect_device(struct input_dev *dev)
514 * that there are no threads in the middle of input_open_device() 515 * that there are no threads in the middle of input_open_device()
515 */ 516 */
516 mutex_lock(&dev->mutex); 517 mutex_lock(&dev->mutex);
517 dev->going_away = 1; 518 dev->going_away = true;
518 mutex_unlock(&dev->mutex); 519 mutex_unlock(&dev->mutex);
519 520
520 spin_lock_irq(&dev->event_lock); 521 spin_lock_irq(&dev->event_lock);
@@ -1259,10 +1260,71 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
1259 return 0; 1260 return 0;
1260} 1261}
1261 1262
1263#define INPUT_DO_TOGGLE(dev, type, bits, on) \
1264 do { \
1265 int i; \
1266 if (!test_bit(EV_##type, dev->evbit)) \
1267 break; \
1268 for (i = 0; i < type##_MAX; i++) { \
1269 if (!test_bit(i, dev->bits##bit) || \
1270 !test_bit(i, dev->bits)) \
1271 continue; \
1272 dev->event(dev, EV_##type, i, on); \
1273 } \
1274 } while (0)
1275
1276static void input_dev_reset(struct input_dev *dev, bool activate)
1277{
1278 if (!dev->event)
1279 return;
1280
1281 INPUT_DO_TOGGLE(dev, LED, led, activate);
1282 INPUT_DO_TOGGLE(dev, SND, snd, activate);
1283
1284 if (activate && test_bit(EV_REP, dev->evbit)) {
1285 dev->event(dev, EV_REP, REP_PERIOD, dev->rep[REP_PERIOD]);
1286 dev->event(dev, EV_REP, REP_DELAY, dev->rep[REP_DELAY]);
1287 }
1288}
1289
1290#ifdef CONFIG_PM
1291static int input_dev_suspend(struct device *dev)
1292{
1293 struct input_dev *input_dev = to_input_dev(dev);
1294
1295 mutex_lock(&input_dev->mutex);
1296 input_dev_reset(input_dev, false);
1297 mutex_unlock(&input_dev->mutex);
1298
1299 return 0;
1300}
1301
1302static int input_dev_resume(struct device *dev)
1303{
1304 struct input_dev *input_dev = to_input_dev(dev);
1305
1306 mutex_lock(&input_dev->mutex);
1307 input_dev_reset(input_dev, true);
1308 mutex_unlock(&input_dev->mutex);
1309
1310 return 0;
1311}
1312
1313static const struct dev_pm_ops input_dev_pm_ops = {
1314 .suspend = input_dev_suspend,
1315 .resume = input_dev_resume,
1316 .poweroff = input_dev_suspend,
1317 .restore = input_dev_resume,
1318};
1319#endif /* CONFIG_PM */
1320
1262static struct device_type input_dev_type = { 1321static struct device_type input_dev_type = {
1263 .groups = input_dev_attr_groups, 1322 .groups = input_dev_attr_groups,
1264 .release = input_dev_release, 1323 .release = input_dev_release,
1265 .uevent = input_dev_uevent, 1324 .uevent = input_dev_uevent,
1325#ifdef CONFIG_PM
1326 .pm = &input_dev_pm_ops,
1327#endif
1266}; 1328};
1267 1329
1268static char *input_nodename(struct device *dev) 1330static char *input_nodename(struct device *dev)