This is part 3 of 5 of a patchset implementing the following in MeeGo kernel:
- Add OMAP DSS2 patches for supporting upgraded SGX driver: linux-2.6.35-OMAP-DSS2-in_use-flag-for-dss_cache.patch linux-2.6.35-OMAP-DSS2-Keep-track-whether-overlay-managers-are-en.patch linux-2.6.35-OMAP-DSS2-Add-GO-notifiers.patch - Upgrade N900 SGX drivers to 201003002 in order to not have a non-production snapshot of the drivers. Fixes BMC#5711 - Add SGX platform device to N900 board file. These patches apply in order: linux-2.6.35-OMAP-DSS2-in_use-flag-for-dss_cache.patch linux-2.6.35-OMAP-DSS2-Keep-track-whether-overlay-managers-are-en.patch linux-2.6.35-OMAP-DSS2-Add-GO-notifiers.patch linux-2.6-N900-add-sgx-platform-device.patch linux-2.6-SGX-N900-upgrade-201003002.patch
From aceedf49ea2dd8bc0d3462ced9fa2ea374193508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <[email protected]> Date: Mon, 24 May 2010 18:41:14 +0300 Subject: [PATCH] OMAP: DSS2: Add GO notifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a notifier mechanism that can be used to signal GO bit changes. The events are basically asynchronous versions of wait_for_go(). The events are fired when the the GO bits are cleared and the caches are clean. For manual update displays the events are fired as soon as the previous manual update has completed. Events for disabled overlays and managers are fired immediately. Signed-off-by: Ville Syrjälä <[email protected]> Signed-off-by: Carsten Valdemar Munk <[email protected]> Index: linux-2.6.34-master/arch/arm/plat-omap/include/plat/display.h =================================================================== --- linux-2.6.34-master.orig/arch/arm/plat-omap/include/plat/display.h 2010-08-04 09:18:17.000000000 +0000 +++ linux-2.6.34-master/arch/arm/plat-omap/include/plat/display.h 2010-08-04 09:18:48.000000000 +0000 @@ -23,6 +23,7 @@ #include <linux/list.h> #include <linux/kobject.h> #include <linux/device.h> +#include <linux/notifier.h> #include <asm/atomic.h> #define DISPC_IRQ_FRAMEDONE (1 << 0) @@ -197,6 +198,11 @@ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, }; +enum omap_dss_notify_event { + OMAP_DSS_NOTIFY_GO_MGR, + OMAP_DSS_NOTIFY_GO_OVL, +}; + /* RFBI */ struct rfbi_timings { @@ -328,6 +334,7 @@ struct omap_overlay_info *info); int (*wait_for_go)(struct omap_overlay *ovl); + int (*notify_go)(struct omap_overlay *ovl); }; struct omap_overlay_manager_info { @@ -371,6 +378,7 @@ int (*apply)(struct omap_overlay_manager *mgr); int (*wait_for_go)(struct omap_overlay_manager *mgr); + int (*notify_go)(struct omap_overlay_manager *mgr); int (*wait_for_vsync)(struct omap_overlay_manager *mgr); int (*enable)(struct omap_overlay_manager *mgr); @@ -548,6 +556,11 @@ u16 *xres, u16 *yres); int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); +int omap_dss_register_notifier(struct notifier_block *nb); +int omap_dss_unregister_notifier(struct notifier_block *nb); + +int omap_dss_request_notify(enum omap_dss_notify_event event, long value); + typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); Index: linux-2.6.34-master/drivers/video/omap2/dss/dss.h =================================================================== --- linux-2.6.34-master.orig/drivers/video/omap2/dss/dss.h 2010-08-04 09:18:24.000000000 +0000 +++ linux-2.6.34-master/drivers/video/omap2/dss/dss.h 2010-08-04 09:18:48.000000000 +0000 @@ -198,6 +198,7 @@ int dss_init_overlay_managers(struct platform_device *pdev); void dss_uninit_overlay_managers(struct platform_device *pdev); int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); +int dss_mgr_notify_go_ovl(struct omap_overlay *ovl); void dss_setup_partial_planes(struct omap_dss_device *dssdev, u16 *x, u16 *y, u16 *w, u16 *h); void dss_start_update(struct omap_dss_device *dssdev); Index: linux-2.6.34-master/drivers/video/omap2/dss/manager.c =================================================================== --- linux-2.6.34-master.orig/drivers/video/omap2/dss/manager.c 2010-08-04 09:18:29.000000000 +0000 +++ linux-2.6.34-master/drivers/video/omap2/dss/manager.c 2010-08-04 09:20:15.000000000 +0000 @@ -25,6 +25,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/notifier.h> #include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/jiffies.h> @@ -415,6 +416,8 @@ u32 fifo_high; bool manual_update; + + bool pending_notify; }; struct manager_cache_data { @@ -444,6 +447,8 @@ u16 x, y, w, h; bool in_use; + + bool pending_notify; }; static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr); @@ -456,6 +461,144 @@ bool irq_enabled; } dss_cache; +static BLOCKING_NOTIFIER_HEAD(dss_notifier_list); + +static int dss_notifier_call_chain(unsigned long val, void *v) +{ + return blocking_notifier_call_chain(&dss_notifier_list, val, v); +} + +static bool check_mgr_notify(struct omap_overlay_manager *mgr) +{ + struct manager_cache_data *mc; + + if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) + return false; + + mc = &dss_cache.manager_cache[mgr->id]; + + if (!mc->pending_notify) + return false; + + if (mc->manual_update) { + if (mc->enabled && mc->in_use && mgr->info_dirty) + return false; + } else { + if (mc->enabled && (mc->dirty || mc->shadow_dirty)) + return false; + } + + return true; +} + +static bool check_ovl_notify(struct omap_overlay *ovl) +{ + struct overlay_cache_data *oc; + struct manager_cache_data *mc; + + if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) + return false; + + oc = &dss_cache.overlay_cache[ovl->id]; + mc = &dss_cache.manager_cache[oc->channel]; + + if (!oc->pending_notify) + return false; + + if (oc->manual_update) { + if (mc->enabled && oc->enabled && + mc->in_use && ovl->info_dirty) + return false; + } else { + if (mc->enabled && oc->enabled && + (oc->dirty || oc->shadow_dirty)) + return false; + } + + return true; +} + +static void dss_notify_worker(struct work_struct *work) +{ + struct overlay_cache_data *oc; + struct manager_cache_data *mc; + const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); + const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); + int i; + unsigned long flags; + bool mgr_notify[2] = { false, false }; + bool ovl_notify[3] = { false, false, false }; + struct omap_overlay_manager *mgr; + struct omap_overlay *ovl; + + spin_lock_irqsave(&dss_cache.lock, flags); + + list_for_each_entry(mgr, &manager_list, list) { + if (!check_mgr_notify(mgr)) + continue; + + mc = &dss_cache.manager_cache[mgr->id]; + + mgr_notify[mgr->id] = true; + mc->pending_notify = false; + } + + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + ovl = omap_dss_get_overlay(i); + + if (!check_ovl_notify(ovl)) + continue; + + oc = &dss_cache.overlay_cache[ovl->id]; + + ovl_notify[ovl->id] = true; + oc->pending_notify = false; + } + + spin_unlock_irqrestore(&dss_cache.lock, flags); + + for (i = 0; i < num_mgrs; i++) { + if (!mgr_notify[i]) + continue; + dss_notifier_call_chain(OMAP_DSS_NOTIFY_GO_MGR, + (void *)(long)i); + } + + for (i = 0; i < num_ovls; i++) { + if (!ovl_notify[i]) + continue; + dss_notifier_call_chain(OMAP_DSS_NOTIFY_GO_OVL, + (void *)(long)i); + } +} + +static DECLARE_WORK(dss_notify_work, dss_notify_worker); + +static void schedule_notify_go(void) +{ + int i; + struct omap_overlay_manager *mgr; + struct omap_overlay *ovl; + + list_for_each_entry(mgr, &manager_list, list) { + if (!check_mgr_notify(mgr)) + continue; + + schedule_work(&dss_notify_work); + break; + } + + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + ovl = omap_dss_get_overlay(i); + + if (!check_ovl_notify(ovl)) + continue; + + schedule_work(&dss_notify_work); + break; + } +} + void omap_dss_lock_cache(void) { unsigned long flags; @@ -472,6 +615,7 @@ spin_lock_irqsave(&dss_cache.lock, flags); BUG_ON(!dss_cache.manager_cache[0].in_use); dss_cache.manager_cache[0].in_use = false; + schedule_notify_go(); spin_unlock_irqrestore(&dss_cache.lock, flags); omap_dss_mgr_apply(omap_dss_get_overlay_manager(0)); } @@ -982,6 +1126,135 @@ *w = x2 - x1; } +static int dss_mgr_notify_go(struct omap_overlay_manager *mgr) +{ + struct manager_cache_data *mc; + const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); + unsigned long flags; + bool dirty; + struct omap_dss_device *dssdev = mgr->device; + + if (mgr->id >= num_mgrs) + return -EINVAL; + + if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { + dss_notifier_call_chain(OMAP_DSS_NOTIFY_GO_MGR, + (void *)(long)mgr->id); + return 0; + } + + spin_lock_irqsave(&dss_cache.lock, flags); + + mc = &dss_cache.manager_cache[mgr->id]; + + if (mc->manual_update) + dirty = mc->enabled && mc->in_use && mgr->info_dirty; + else + dirty = mc->enabled && (mc->dirty || mc->shadow_dirty); + + mc->pending_notify = dirty; + + spin_unlock_irqrestore(&dss_cache.lock, flags); + + if (!dirty) + dss_notifier_call_chain(OMAP_DSS_NOTIFY_GO_MGR, + (void *)(long)mgr->id); + + return 0; +} + +int dss_mgr_notify_go_ovl(struct omap_overlay *ovl) +{ + struct overlay_cache_data *oc; + struct manager_cache_data *mc; + const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); + unsigned long flags; + bool dirty; + struct omap_dss_device *dssdev; + + if (ovl->id >= num_ovls) + return -EINVAL; + + if (!ovl->manager) { + dss_notifier_call_chain(OMAP_DSS_NOTIFY_GO_OVL, + (void *)(long)ovl->id); + return 0; + } + + dssdev = ovl->manager->device; + + if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { + dss_notifier_call_chain(OMAP_DSS_NOTIFY_GO_OVL, + (void *)(long)ovl->id); + return 0; + } + + spin_lock_irqsave(&dss_cache.lock, flags); + + oc = &dss_cache.overlay_cache[ovl->id]; + mc = &dss_cache.manager_cache[oc->channel]; + + if (oc->manual_update) + dirty = mc->enabled && oc->enabled && + mc->in_use && ovl->info_dirty; + else + dirty = mc->enabled && oc->enabled && + (oc->dirty || oc->shadow_dirty); + + oc->pending_notify = dirty; + + spin_unlock_irqrestore(&dss_cache.lock, flags); + + if (!dirty) + dss_notifier_call_chain(OMAP_DSS_NOTIFY_GO_OVL, + (void *)(long)ovl->id); + + return 0; +} + +int omap_dss_request_notify(enum omap_dss_notify_event event, + long value) +{ + struct omap_overlay_manager *mgr; + struct omap_overlay *ovl; + + switch (event) { + case OMAP_DSS_NOTIFY_GO_MGR: + mgr = omap_dss_get_overlay_manager(value); + if (!mgr) + return -EINVAL; + if (!mgr->notify_go) + return -ENOSYS; + mgr->notify_go(mgr); + break; + case OMAP_DSS_NOTIFY_GO_OVL: + ovl = omap_dss_get_overlay(value); + if (!ovl) + return -EINVAL; + if (!ovl->notify_go) + return -ENOSYS; + ovl->notify_go(ovl); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(omap_dss_request_notify); + +int omap_dss_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&dss_notifier_list, nb); +} +EXPORT_SYMBOL(omap_dss_register_notifier); + +int omap_dss_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&dss_notifier_list, nb); +} +EXPORT_SYMBOL(omap_dss_unregister_notifier); + /* Configure dispc for partial update. Return possibly modified update * area */ void dss_setup_partial_planes(struct omap_dss_device *dssdev, @@ -1175,6 +1448,7 @@ dss_cache.irq_enabled = false; end: + schedule_notify_go(); spin_unlock(&dss_cache.lock); } @@ -1452,6 +1726,7 @@ spin_lock_irqsave(&dss_cache.lock, flags); mc->enabled = false; + schedule_notify_go(); spin_unlock_irqrestore(&dss_cache.lock, flags); return 0; @@ -1500,6 +1775,7 @@ mgr->set_manager_info = &omap_dss_mgr_set_info; mgr->get_manager_info = &omap_dss_mgr_get_info; mgr->wait_for_go = &dss_mgr_wait_for_go; + mgr->notify_go = &dss_mgr_notify_go; mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; mgr->enable = &dss_mgr_enable; Index: linux-2.6.34-master/drivers/video/omap2/dss/overlay.c =================================================================== --- linux-2.6.34-master.orig/drivers/video/omap2/dss/overlay.c 2010-08-04 09:18:34.000000000 +0000 +++ linux-2.6.34-master/drivers/video/omap2/dss/overlay.c 2010-08-04 09:18:48.000000000 +0000 @@ -428,6 +428,11 @@ return dss_mgr_wait_for_go_ovl(ovl); } +static int dss_ovl_notify_go(struct omap_overlay *ovl) +{ + return dss_mgr_notify_go_ovl(ovl); +} + static int omap_dss_set_manager(struct omap_overlay *ovl, struct omap_overlay_manager *mgr) { @@ -578,6 +583,7 @@ ovl->set_overlay_info = &dss_ovl_set_overlay_info; ovl->get_overlay_info = &dss_ovl_get_overlay_info; ovl->wait_for_go = &dss_ovl_wait_for_go; + ovl->notify_go = &dss_ovl_notify_go; omap_dss_add_overlay(ovl);
_______________________________________________ MeeGo-dev mailing list [email protected] http://lists.meego.com/listinfo/meego-dev
