diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-07-01 12:07:33 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-07-03 16:13:21 -0400 |
commit | af6e1d99ea525161f70f68ecb83d0d0f54f1bf62 (patch) | |
tree | 5d805e4e6da3f252bd9b4d8a958b25723970837f /drivers/input/misc/adxl34x.c | |
parent | 963ce8ae6dbc7c8dffb1b117ba14673d40b22dda (diff) |
Input: adxl34 - make enable/disable separate from suspend/resume
Suspending and resuming the device should be separate from enabling
and disabling it through sysfs attribute and thus should not alter
ac->disabled flag.
[michael.hennerich@analog.com: various fixups]
Tested-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/misc/adxl34x.c')
-rw-r--r-- | drivers/input/misc/adxl34x.c | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 77fb40987059..bb9c10f9dfd3 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c | |||
@@ -200,6 +200,7 @@ struct adxl34x { | |||
200 | unsigned orient3d_saved; | 200 | unsigned orient3d_saved; |
201 | bool disabled; /* P: mutex */ | 201 | bool disabled; /* P: mutex */ |
202 | bool opened; /* P: mutex */ | 202 | bool opened; /* P: mutex */ |
203 | bool suspended; /* P: mutex */ | ||
203 | bool fifo_delay; | 204 | bool fifo_delay; |
204 | int irq; | 205 | int irq; |
205 | unsigned model; | 206 | unsigned model; |
@@ -399,41 +400,44 @@ static irqreturn_t adxl34x_irq(int irq, void *handle) | |||
399 | 400 | ||
400 | static void __adxl34x_disable(struct adxl34x *ac) | 401 | static void __adxl34x_disable(struct adxl34x *ac) |
401 | { | 402 | { |
402 | if (!ac->disabled && ac->opened) { | 403 | /* |
403 | /* | 404 | * A '0' places the ADXL34x into standby mode |
404 | * A '0' places the ADXL34x into standby mode | 405 | * with minimum power consumption. |
405 | * with minimum power consumption. | 406 | */ |
406 | */ | 407 | AC_WRITE(ac, POWER_CTL, 0); |
407 | AC_WRITE(ac, POWER_CTL, 0); | ||
408 | |||
409 | ac->disabled = true; | ||
410 | } | ||
411 | } | 408 | } |
412 | 409 | ||
413 | static void __adxl34x_enable(struct adxl34x *ac) | 410 | static void __adxl34x_enable(struct adxl34x *ac) |
414 | { | 411 | { |
415 | if (ac->disabled && ac->opened) { | 412 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); |
416 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); | ||
417 | ac->disabled = false; | ||
418 | } | ||
419 | } | 413 | } |
420 | 414 | ||
421 | void adxl34x_disable(struct adxl34x *ac) | 415 | void adxl34x_suspend(struct adxl34x *ac) |
422 | { | 416 | { |
423 | mutex_lock(&ac->mutex); | 417 | mutex_lock(&ac->mutex); |
424 | __adxl34x_disable(ac); | 418 | |
419 | if (!ac->suspended && !ac->disabled && ac->opened) | ||
420 | __adxl34x_disable(ac); | ||
421 | |||
422 | ac->suspended = true; | ||
423 | |||
425 | mutex_unlock(&ac->mutex); | 424 | mutex_unlock(&ac->mutex); |
426 | } | 425 | } |
427 | EXPORT_SYMBOL_GPL(adxl34x_disable); | 426 | EXPORT_SYMBOL_GPL(adxl34x_suspend); |
428 | 427 | ||
429 | void adxl34x_enable(struct adxl34x *ac) | 428 | void adxl34x_resume(struct adxl34x *ac) |
430 | { | 429 | { |
431 | mutex_lock(&ac->mutex); | 430 | mutex_lock(&ac->mutex); |
432 | __adxl34x_enable(ac); | 431 | |
432 | if (ac->suspended && !ac->disabled && ac->opened) | ||
433 | __adxl34x_enable(ac); | ||
434 | |||
435 | ac->suspended= false; | ||
436 | |||
433 | mutex_unlock(&ac->mutex); | 437 | mutex_unlock(&ac->mutex); |
434 | } | 438 | } |
435 | 439 | ||
436 | EXPORT_SYMBOL_GPL(adxl34x_enable); | 440 | EXPORT_SYMBOL_GPL(adxl34x_resume); |
437 | 441 | ||
438 | static ssize_t adxl34x_disable_show(struct device *dev, | 442 | static ssize_t adxl34x_disable_show(struct device *dev, |
439 | struct device_attribute *attr, char *buf) | 443 | struct device_attribute *attr, char *buf) |
@@ -455,10 +459,21 @@ static ssize_t adxl34x_disable_store(struct device *dev, | |||
455 | if (error) | 459 | if (error) |
456 | return error; | 460 | return error; |
457 | 461 | ||
458 | if (val) | 462 | mutex_lock(&ac->mutex); |
459 | adxl34x_disable(ac); | 463 | |
460 | else | 464 | if (!ac->suspended && ac->opened) { |
461 | adxl34x_enable(ac); | 465 | if (val) { |
466 | if (!ac->disabled) | ||
467 | __adxl34x_disable(ac); | ||
468 | } else { | ||
469 | if (ac->disabled) | ||
470 | __adxl34x_enable(ac); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | ac->disabled = !!val; | ||
475 | |||
476 | mutex_unlock(&ac->mutex); | ||
462 | 477 | ||
463 | return count; | 478 | return count; |
464 | } | 479 | } |
@@ -575,7 +590,7 @@ static ssize_t adxl34x_autosleep_store(struct device *dev, | |||
575 | else | 590 | else |
576 | ac->pdata.power_mode &= ~(PCTL_AUTO_SLEEP | PCTL_LINK); | 591 | ac->pdata.power_mode &= ~(PCTL_AUTO_SLEEP | PCTL_LINK); |
577 | 592 | ||
578 | if (!ac->disabled && ac->opened) | 593 | if (!ac->disabled && !ac->suspended && ac->opened) |
579 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); | 594 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); |
580 | 595 | ||
581 | mutex_unlock(&ac->mutex); | 596 | mutex_unlock(&ac->mutex); |
@@ -649,8 +664,12 @@ static int adxl34x_input_open(struct input_dev *input) | |||
649 | struct adxl34x *ac = input_get_drvdata(input); | 664 | struct adxl34x *ac = input_get_drvdata(input); |
650 | 665 | ||
651 | mutex_lock(&ac->mutex); | 666 | mutex_lock(&ac->mutex); |
667 | |||
668 | if (!ac->suspended && !ac->disabled) | ||
669 | __adxl34x_enable(ac); | ||
670 | |||
652 | ac->opened = true; | 671 | ac->opened = true; |
653 | __adxl34x_enable(ac); | 672 | |
654 | mutex_unlock(&ac->mutex); | 673 | mutex_unlock(&ac->mutex); |
655 | 674 | ||
656 | return 0; | 675 | return 0; |
@@ -661,8 +680,12 @@ static void adxl34x_input_close(struct input_dev *input) | |||
661 | struct adxl34x *ac = input_get_drvdata(input); | 680 | struct adxl34x *ac = input_get_drvdata(input); |
662 | 681 | ||
663 | mutex_lock(&ac->mutex); | 682 | mutex_lock(&ac->mutex); |
664 | __adxl34x_disable(ac); | 683 | |
684 | if (!ac->suspended && !ac->disabled) | ||
685 | __adxl34x_disable(ac); | ||
686 | |||
665 | ac->opened = false; | 687 | ac->opened = false; |
688 | |||
666 | mutex_unlock(&ac->mutex); | 689 | mutex_unlock(&ac->mutex); |
667 | } | 690 | } |
668 | 691 | ||
@@ -878,7 +901,6 @@ EXPORT_SYMBOL_GPL(adxl34x_probe); | |||
878 | 901 | ||
879 | int adxl34x_remove(struct adxl34x *ac) | 902 | int adxl34x_remove(struct adxl34x *ac) |
880 | { | 903 | { |
881 | adxl34x_disable(ac); | ||
882 | sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group); | 904 | sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group); |
883 | free_irq(ac->irq, ac); | 905 | free_irq(ac->irq, ac); |
884 | input_unregister_device(ac->input); | 906 | input_unregister_device(ac->input); |