diff options
-rw-r--r-- | drivers/video/omap2/dsscomp/device.c | 4 | ||||
-rw-r--r-- | drivers/video/omap2/dsscomp/dsscomp.h | 3 | ||||
-rw-r--r-- | drivers/video/omap2/dsscomp/queue.c | 36 |
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); |