aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-08-12 20:25:25 -0500
committerIliyan Malchev <malchev@google.com>2011-08-17 11:58:57 -0700
commit1e399ff39999260e59ac088eccb4e9f78b05db08 (patch)
tree2bad46e1f80a26807d7416cf6d7cafc98c7b599b
parentd9f2305708d2a546a0d8b1e4f9c713f71cca8a0f (diff)
downloadkernel_samsung_tuna-1e399ff39999260e59ac088eccb4e9f78b05db08.zip
kernel_samsung_tuna-1e399ff39999260e59ac088eccb4e9f78b05db08.tar.gz
kernel_samsung_tuna-1e399ff39999260e59ac088eccb4e9f78b05db08.tar.bz2
OMAP:DSS2: Add manager blanking support
Add manager->blank() to disable all overlays on a manager from all the dss_cache stages. blank() takes 2 additional arguments beyond the manager. wait_for_vsync: to wait for vsync before flush returns. persist: to disable subsequent applies until the display is turned off/suspended. if wait_for_vsync is false, blank() will flush the callbacks in the shadow and displayed stages of the dss cache. You may want to use this if there are no further VSYNCS for the display. This is safe because the dss_cache is updated for the blanked overlays, so it will take effect the next time configure() is called. Change-Id: Ic4bbd4ef73246ee89bdc8699b4bc09efffafe51f Signed-off-by: Lajos Molnar <molnar@ti.com>
-rw-r--r--drivers/video/omap2/dss/manager.c116
-rw-r--r--include/video/omapdss.h1
2 files changed, 117 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index faf5590..730fb2b 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -28,6 +28,7 @@
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
+#include <linux/ratelimit.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
@@ -1556,6 +1557,112 @@ end:
spin_unlock(&dss_cache.lock);
}
+static int omap_dss_mgr_blank(struct omap_overlay_manager *mgr,
+ bool wait_for_vsync)
+{
+ struct overlay_cache_data *oc;
+ struct manager_cache_data *mc;
+ unsigned long flags;
+ int r, r_get, i;
+
+ DSSDBG("omap_dss_mgr_blank(%s,vsync=%d)\n", mgr->name, wait_for_vsync);
+
+ r_get = r = dispc_runtime_get();
+ /* still clear cache even if failed to get clocks, just don't config */
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+
+ /* disable overlays in overlay info structs and in cache */
+ for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+ struct omap_overlay_info oi = { .enabled = false };
+ struct omap_overlay *ovl;
+
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC) ||
+ ovl->manager != mgr)
+ continue;
+
+ oc = &dss_cache.overlay_cache[ovl->id];
+
+ /* complete unconfigured info in cache */
+ dss_ovl_cb(&oc->cb.cache, i, DSS_COMPLETION_ECLIPSED_CACHE);
+ oc->cb.cache.fn = NULL;
+
+ ovl->info = oi;
+ ovl->info_dirty = false;
+ oc->dirty = true;
+ oc->enabled = false;
+ }
+
+ /* dirty manager */
+ mc = &dss_cache.manager_cache[mgr->id];
+ dss_ovl_cb(&mc->cb.cache, i, DSS_COMPLETION_ECLIPSED_CACHE);
+ mc->cb.cache.fn = NULL;
+ mgr->info.cb.fn = NULL;
+ mc->dirty = true;
+ mgr->info_dirty = false;
+
+ /*
+ * TRICKY: Enable apply irq even if not waiting for vsync, so that
+ * DISPC programming takes place in case GO bit was on.
+ */
+ if (dss_cache.irq_enabled) {
+ u32 mask;
+
+ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
+ DISPC_IRQ_EVSYNC_EVEN;
+ if (dss_has_feature(FEAT_MGR_LCD2))
+ mask |= DISPC_IRQ_VSYNC2;
+
+ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
+ dss_cache.irq_enabled = true;
+ }
+
+ if (!r_get) {
+ r = configure_dispc();
+ if (r)
+ pr_info("mgr_blank while GO is set");
+ }
+
+ if (r_get || !wait_for_vsync) {
+ /* pretend that programming has happened */
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ oc = &dss_cache.overlay_cache[i];
+ if (oc->channel != mgr->id)
+ continue;
+ if (r && oc->dirty)
+ dss_ovl_configure_cb(&oc->cb, i, false);
+ if (oc->shadow_dirty) {
+ dss_ovl_program_cb(&oc->cb, i);
+ oc->dispc_channel = oc->channel;
+ oc->shadow_dirty = false;
+ } else {
+ pr_warn("ovl%d-shadow is not dirty\n", i);
+ }
+ }
+
+ if (r && mc->dirty)
+ dss_ovl_configure_cb(&mc->cb, i, false);
+ if (mc->shadow_dirty) {
+ dss_ovl_program_cb(&mc->cb, i);
+ mc->shadow_dirty = false;
+ } else {
+ pr_warn("mgr%d-shadow is not dirty\n", mgr->id);
+ }
+ }
+
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
+ if (wait_for_vsync && !r)
+ mgr->wait_for_vsync(mgr);
+
+ if (!r_get)
+ dispc_runtime_put();
+
+ return r;
+}
+
static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
{
struct overlay_cache_data *oc;
@@ -1576,6 +1683,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
spin_lock_irqsave(&dss_cache.lock, flags);
+ if (!mgr->device || mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ pr_info_ratelimited("cannot apply mgr(%s) on inactive device\n",
+ mgr->name);
+ r = -ENODEV;
+ goto done;
+ }
+
/* Configure overlays */
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
struct omap_dss_device *dssdev;
@@ -1792,6 +1906,7 @@ skip_mgr:
}
configure_dispc();
+done:
spin_unlock_irqrestore(&dss_cache.lock, flags);
dispc_runtime_put();
@@ -1947,6 +2062,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
mgr->get_manager_info = &omap_dss_mgr_get_info;
mgr->wait_for_go = &dss_mgr_wait_for_go;
mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
+ mgr->blank = &omap_dss_mgr_blank;
mgr->enable = &dss_mgr_enable;
mgr->disable = &dss_mgr_disable;
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3b82dd5..65d9702 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -457,6 +457,7 @@ struct omap_overlay_manager {
int (*apply)(struct omap_overlay_manager *mgr);
int (*wait_for_go)(struct omap_overlay_manager *mgr);
int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
+ int (*blank)(struct omap_overlay_manager *mgr, bool wait_for_vsync);
int (*enable)(struct omap_overlay_manager *mgr);
int (*disable)(struct omap_overlay_manager *mgr);