summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAravind Venkateswaran <aravindh@codeaurora.org>2014-02-06 18:27:27 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:27:15 -0700
commit824b24b09cd46a4d1d95e0cb2cc433f8fbe87f74 (patch)
treeacc13d3dde3521548dba4ecaaaf76fa26702ff5b
parentfa1682856035b3230a17605166e64f75797aa584 (diff)
msm: mdss: Notify userspace of idle screen case
Expose two new sysfs nodes - idle_time and idle_notify - that are used to notify userspace whenever the display is idle with no screen updates. The idle_time node needs to be configured with the duration in milliseconds to detect no screen updates. The userspace app can poll on the idle_notify node to get notifications of the idle state. Change-Id: I7435a084ad2c928d952c5d106ff9ef92aaa385b9 Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c76
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h3
2 files changed, 79 insertions, 0 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 4f6f204069aa..c68b1c25797e 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -327,14 +327,75 @@ static ssize_t mdss_mdp_show_blank_event(struct device *dev,
return ret;
}
+static void __mdss_fb_idle_notify_work(struct work_struct *work)
+{
+ struct delayed_work *dw = to_delayed_work(work);
+ struct msm_fb_data_type *mfd = container_of(dw, struct msm_fb_data_type,
+ idle_notify_work);
+
+ /* Notify idle-ness here */
+ pr_debug("Idle timeout %dms expired!\n", mfd->idle_time);
+ sysfs_notify(&mfd->fbi->dev->kobj, NULL, "idle_notify");
+}
+
+static ssize_t mdss_fb_get_idle_time(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ int ret;
+
+ ret = scnprintf(buf, PAGE_SIZE, "%d", mfd->idle_time);
+
+ return ret;
+}
+
+static ssize_t mdss_fb_set_idle_time(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ int rc = 0;
+ int idle_time = 0;
+
+ rc = kstrtoint(buf, 10, &idle_time);
+ if (rc) {
+ pr_err("kstrtoint failed. rc=%d\n", rc);
+ return rc;
+ }
+
+ pr_debug("Idle time = %d\n", idle_time);
+ mfd->idle_time = idle_time;
+
+ return count;
+}
+
+static ssize_t mdss_fb_get_idle_notify(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ int ret;
+
+ ret = scnprintf(buf, PAGE_SIZE, "%s",
+ work_busy(&mfd->idle_notify_work.work) ? "no" : "yes");
+
+ return ret;
+}
+
static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, S_IRUGO, mdss_fb_get_split, NULL);
static DEVICE_ATTR(show_blank_event, S_IRUGO, mdss_mdp_show_blank_event, NULL);
+static DEVICE_ATTR(idle_time, S_IRUGO | S_IWUSR | S_IWGRP,
+ mdss_fb_get_idle_time, mdss_fb_set_idle_time);
+static DEVICE_ATTR(idle_notify, S_IRUGO, mdss_fb_get_idle_notify, NULL);
static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_type.attr,
&dev_attr_msm_fb_split.attr,
&dev_attr_show_blank_event.attr,
+ &dev_attr_idle_time.attr,
+ &dev_attr_idle_notify.attr,
NULL,
};
@@ -489,6 +550,8 @@ static int mdss_fb_probe(struct platform_device *pdev)
}
}
+ INIT_DELAYED_WORK(&mfd->idle_notify_work, __mdss_fb_idle_notify_work);
+
return rc;
}
@@ -803,6 +866,11 @@ static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
mfd->update.type = NOTIFY_TYPE_UPDATE;
mfd->update.is_suspend = 0;
mutex_unlock(&mfd->update.lock);
+
+ /* Start the work thread to signal idle time */
+ if (mfd->idle_time)
+ schedule_delayed_work(&mfd->idle_notify_work,
+ msecs_to_jiffies(mfd->idle_time));
}
break;
@@ -1555,10 +1623,18 @@ static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
unsigned long event, void *data)
{
struct msm_sync_pt_data *sync_pt_data;
+ struct msm_fb_data_type *mfd;
sync_pt_data = container_of(p, struct msm_sync_pt_data, notifier);
+ mfd = container_of(sync_pt_data, struct msm_fb_data_type,
+ mdp_sync_pt_data);
switch (event) {
+ case MDP_NOTIFY_FRAME_BEGIN:
+ if (mfd->idle_time)
+ mod_delayed_work(system_wq, &mfd->idle_notify_work,
+ msecs_to_jiffies(mfd->idle_time));
+ break;
case MDP_NOTIFY_FRAME_READY:
if (sync_pt_data->async_wait_fences)
mdss_fb_wait_for_fence(sync_pt_data);
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index 6718da87cd23..7811f7f9f347 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -172,6 +172,9 @@ struct msm_fb_data_type {
u32 dest;
struct fb_info *fbi;
+ int idle_time;
+ struct delayed_work idle_notify_work;
+
int op_enable;
u32 fb_imgType;
int panel_reconfig;