framebuffer: add a pollable sysfs entry for display status

Wakeup the userspace poll on change of display status. The
userspace then may take action to change the
power/performance characteristics of the device.

Change-Id: I9bd11f3d895d3d83230104f5d8dcd1deeaa754cd
Signed-off-by: Amar Singhal <asinghal@codeaurora.org>
diff --git a/kernel/power/fbearlysuspend.c b/kernel/power/fbearlysuspend.c
index 1513765..4877372 100644
--- a/kernel/power/fbearlysuspend.c
+++ b/kernel/power/fbearlysuspend.c
@@ -19,7 +19,10 @@
 
 #include "power.h"
 
+#define MAX_BUF 100
+
 static wait_queue_head_t fb_state_wq;
+static int display = 1;
 static DEFINE_SPINLOCK(fb_state_lock);
 static enum {
 	FB_STATE_STOPPED_DRAWING,
@@ -71,10 +74,16 @@
 
 	ret = wait_event_interruptible(fb_state_wq,
 				       fb_state != FB_STATE_DRAWING_OK);
-	if (ret && fb_state == FB_STATE_DRAWING_OK)
+	if (ret && fb_state == FB_STATE_DRAWING_OK) {
 		return ret;
-	else
+	} else {
 		s += sprintf(buf, "sleeping");
+		if (display == 1) {
+			display = 0;
+			sysfs_notify(power_kobj, NULL, "wait_for_fb_status");
+		}
+	}
+
 	return s - buf;
 }
 
@@ -96,28 +105,47 @@
 				       fb_state == FB_STATE_DRAWING_OK);
 	if (ret && fb_state != FB_STATE_DRAWING_OK)
 		return ret;
-	else
+	else {
 		s += sprintf(buf, "awake");
-
+		if (display == 0) {
+			display = 1;
+			sysfs_notify(power_kobj, NULL, "wait_for_fb_status");
+		}
+	}
 	return s - buf;
 }
 
-#define power_ro_attr(_name) \
-static struct kobj_attribute _name##_attr = {	\
-	.attr	= {				\
-		.name = __stringify(_name),	\
-		.mode = 0444,			\
-	},					\
-	.show	= _name##_show,			\
-	.store	= NULL,		\
+static ssize_t wait_for_fb_status_show(struct kobject *kobj,
+				       struct kobj_attribute *attr, char *buf)
+{
+	int ret = 0;
+
+	if (display == 1)
+		ret = snprintf(buf, strnlen("on", MAX_BUF) + 1, "on");
+	else
+		ret = snprintf(buf, strnlen("off", MAX_BUF) + 1, "off");
+
+	return ret;
 }
 
+#define power_ro_attr(_name)				\
+	static struct kobj_attribute _name##_attr = {	\
+		.attr	= {				\
+			.name = __stringify(_name),	\
+			.mode = 0444,			\
+		},					\
+		.show	= _name##_show,			\
+		.store	= NULL,				\
+	}
+
 power_ro_attr(wait_for_fb_sleep);
 power_ro_attr(wait_for_fb_wake);
+power_ro_attr(wait_for_fb_status);
 
 static struct attribute *g[] = {
 	&wait_for_fb_sleep_attr.attr,
 	&wait_for_fb_wake_attr.attr,
+	&wait_for_fb_status_attr.attr,
 	NULL,
 };