diff options
author | Lajos Molnar <molnar@ti.com> | 2011-08-12 20:25:25 -0500 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2011-08-17 11:58:57 -0700 |
commit | 1e399ff39999260e59ac088eccb4e9f78b05db08 (patch) | |
tree | 2bad46e1f80a26807d7416cf6d7cafc98c7b599b | |
parent | d9f2305708d2a546a0d8b1e4f9c713f71cca8a0f (diff) | |
download | kernel_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.c | 116 | ||||
-rw-r--r-- | include/video/omapdss.h | 1 |
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); |