kernel/power: add pollable sysfs entries for touch events

Provide userspace with a pollable sysfs entry that it can poll
on waiting for touch event notifiction. Once it
is woken up, the userspace can take action to change the
power/performance characteristics of the device for the duration
of the event.

Change-Id: Iab84f729f2ea3a5352c4e5173f78544023a276c1
Signed-off-by: Amar Singhal <asinghal@codeaurora.org>
(cherry picked from commit ac2a6d6453c50db7ba7c0b3aa328a3ba48a84abf)
This commit is contained in:
Amar Singhal
2012-02-27 17:40:31 -08:00
committed by Stephen Boyd
parent da87d74481
commit 6cc6e7bc61

View File

@@ -18,6 +18,8 @@
#include "power.h"
#define MAX_BUF 100
DEFINE_MUTEX(pm_mutex);
#ifdef CONFIG_PM_SLEEP
@@ -26,6 +28,10 @@ DEFINE_MUTEX(pm_mutex);
static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
static struct hrtimer in_ev_timer;
static int input_processed;
static ktime_t touch_evt_timer_val;
int register_pm_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&pm_chain_head, nb);
@@ -71,6 +77,72 @@ static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
power_attr(pm_async);
static ssize_t
touch_event_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
if (input_processed == 0)
return snprintf(buf, strnlen("touch_event", MAX_BUF) + 1,
"touch_event");
else
return snprintf(buf, strnlen("null", MAX_BUF) + 1,
"null");
}
static ssize_t
touch_event_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t n)
{
hrtimer_cancel(&in_ev_timer);
input_processed = 0;
/* set a timer to notify the userspace to stop processing
* touch event
*/
hrtimer_start(&in_ev_timer, touch_evt_timer_val, HRTIMER_MODE_REL);
/* wakeup the userspace poll */
sysfs_notify(kobj, NULL, "touch_event");
return n;
}
power_attr(touch_event);
static ssize_t
touch_event_timer_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return snprintf(buf, MAX_BUF, "%lld", touch_evt_timer_val.tv64);
}
static ssize_t
touch_event_timer_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t n)
{
unsigned long val;
if (strict_strtoul(buf, 10, &val))
return -EINVAL;
touch_evt_timer_val = ktime_set(0, val*1000);
return n;
}
power_attr(touch_event_timer);
static enum hrtimer_restart input_event_stop(struct hrtimer *hrtimer)
{
/* wakeup the userspace poll */
input_processed = 1;
sysfs_notify(power_kobj, NULL, "touch_event");
return HRTIMER_NORESTART;
}
#ifdef CONFIG_PM_DEBUG
int pm_test_level = TEST_NONE;
@@ -405,7 +477,7 @@ power_attr(wake_lock);
power_attr(wake_unlock);
#endif
static struct attribute * g[] = {
static struct attribute *g[] = {
&state_attr.attr,
#ifdef CONFIG_PM_TRACE
&pm_trace_attr.attr,
@@ -414,6 +486,8 @@ static struct attribute * g[] = {
#ifdef CONFIG_PM_SLEEP
&pm_async_attr.attr,
&wakeup_count_attr.attr,
&touch_event_attr.attr,
&touch_event_timer_attr.attr,
#ifdef CONFIG_PM_DEBUG
&pm_test_attr.attr,
#endif
@@ -450,6 +524,11 @@ static int __init pm_init(void)
return error;
hibernate_image_size_init();
hibernate_reserved_size_init();
touch_evt_timer_val = ktime_set(2, 0);
hrtimer_init(&in_ev_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
in_ev_timer.function = &input_event_stop;
power_kobj = kobject_create_and_add("power", NULL);
if (!power_kobj)
return -ENOMEM;