diff options
| author | Aravind Venkateswaran <aravindh@codeaurora.org> | 2014-02-06 18:27:27 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:27:15 -0700 |
| commit | 824b24b09cd46a4d1d95e0cb2cc433f8fbe87f74 (patch) | |
| tree | acc13d3dde3521548dba4ecaaaf76fa26702ff5b | |
| parent | fa1682856035b3230a17605166e64f75797aa584 (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.c | 76 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.h | 3 |
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; |
