aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-08-12 20:03:05 -0500
committerIliyan Malchev <malchev@google.com>2011-08-17 11:59:02 -0700
commitf1b02cbfd498bab3a1cf38f7d872a77ca89c9c94 (patch)
tree3105c9249205ddbea767479583a86b720f35d34e
parent1e399ff39999260e59ac088eccb4e9f78b05db08 (diff)
downloadkernel_samsung_tuna-f1b02cbfd498bab3a1cf38f7d872a77ca89c9c94.zip
kernel_samsung_tuna-f1b02cbfd498bab3a1cf38f7d872a77ca89c9c94.tar.gz
kernel_samsung_tuna-f1b02cbfd498bab3a1cf38f7d872a77ca89c9c94.tar.bz2
OMAP:DSSCOMP: Blank manager before turning off its display
Flush displayed content by blanking the manager of the display to be turned off. Otherwise, we will be waiting for VSYNC on that display indefinitely to release the queued frames. Change-Id: I2a2b85e58f5373d968083dd47505e8285aa6b4fa Signed-off-by: Lajos Molnar <molnar@ti.com>
-rw-r--r--drivers/video/omap2/dsscomp/device.c4
-rw-r--r--drivers/video/omap2/dsscomp/dsscomp.h3
-rw-r--r--drivers/video/omap2/dsscomp/queue.c36
3 files changed, 40 insertions, 3 deletions
diff --git a/drivers/video/omap2/dsscomp/device.c b/drivers/video/omap2/dsscomp/device.c
index eb57c4a..773931a 100644
--- a/drivers/video/omap2/dsscomp/device.c
+++ b/drivers/video/omap2/dsscomp/device.c
@@ -369,6 +369,10 @@ static void fill_cache(struct dsscomp_dev *cdev)
cdev->displays[i] = dssdev;
dev_dbg(DEV(cdev), "display%lu=%s\n", i, dssdev->driver_name);
+
+ cdev->state_notifiers[i].notifier_call = dsscomp_state_notifier;
+ blocking_notifier_chain_register(&dssdev->state_notifiers,
+ cdev->state_notifiers + i);
}
dev_info(DEV(cdev), "found %d displays and %d overlays\n",
cdev->num_displays, cdev->num_ovls);
diff --git a/drivers/video/omap2/dsscomp/dsscomp.h b/drivers/video/omap2/dsscomp/dsscomp.h
index 6deeda0..82e50cd 100644
--- a/drivers/video/omap2/dsscomp/dsscomp.h
+++ b/drivers/video/omap2/dsscomp/dsscomp.h
@@ -59,6 +59,7 @@ struct dsscomp_dev {
struct omap_overlay_manager *mgrs[MAX_MANAGERS];
u32 num_displays;
struct omap_dss_device *displays[MAX_DISPLAYS];
+ struct notifier_block state_notifiers[MAX_DISPLAYS];
};
extern int debug;
@@ -112,6 +113,8 @@ void dsscomp_gralloc_exit(void);
int dsscomp_gralloc_queue_ioctl(struct dsscomp_setup_dispc_data *d);
int dsscomp_wait(struct dsscomp_sync_obj *sync, enum dsscomp_wait_phase phase,
int timeout);
+int dsscomp_state_notifier(struct notifier_block *nb,
+ unsigned long arg, void *ptr);
/* basic operation - if not using queues */
int set_dss_ovl_info(struct dss2_ovl_info *oi);
diff --git a/drivers/video/omap2/dsscomp/queue.c b/drivers/video/omap2/dsscomp/queue.c
index 3616ccd..0f8c8a6 100644
--- a/drivers/video/omap2/dsscomp/queue.c
+++ b/drivers/video/omap2/dsscomp/queue.c
@@ -23,6 +23,7 @@
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/ratelimit.h>
#include <video/omapdss.h>
#include <video/dsscomp.h>
@@ -44,6 +45,7 @@ static struct {
u32 ovl_mask; /* overlays used on this display */
struct maskref ovl_qmask; /* overlays queued to this display */
+ bool blanking;
} mgrq[MAX_MANAGERS];
static struct workqueue_struct *cb_wkq; /* callback work queue */
@@ -545,9 +547,17 @@ skip_ovl_set:
if (!d->win.h && !d->win.y)
d->win.h = dssdev->panel.timings.y_res - d->win.y;
- r = mgr->apply(mgr);
- if (r)
- dev_err(DEV(cdev), "failed while applying %d", r);
+ mutex_lock(&mtx);
+ if (mgrq[comp->ix].blanking) {
+ pr_info_ratelimited("ignoring apply mgr(%s) while blanking\n",
+ mgr->name);
+ r = -ENODEV;
+ } else {
+ r = mgr->apply(mgr);
+ if (r)
+ dev_err(DEV(cdev), "failed while applying %d", r);
+ }
+ mutex_unlock(&mtx);
/* ignore this error if callback has already been registered */
if (!mgr->info_dirty)
@@ -576,6 +586,26 @@ struct dsscomp_apply_work {
dsscomp_t comp;
};
+int dsscomp_state_notifier(struct notifier_block *nb,
+ unsigned long arg, void *ptr)
+{
+ struct omap_dss_device *dssdev = ptr;
+ enum omap_dss_display_state state = arg;
+ struct omap_overlay_manager *mgr = dssdev->manager;
+ if (mgr) {
+ mutex_lock(&mtx);
+ if (state == OMAP_DSS_DISPLAY_DISABLED) {
+ mgr->blank(mgr, false);
+ mgrq[mgr->id].blanking = true;
+ } else if (state == OMAP_DSS_DISPLAY_ACTIVE) {
+ mgrq[mgr->id].blanking = false;
+ }
+ mutex_unlock(&mtx);
+ }
+ return 0;
+}
+
+
static void dsscomp_do_apply(struct work_struct *work)
{
struct dsscomp_apply_work *wk = container_of(work, typeof(*wk), work);