diff options
| author | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:18:27 +0200 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:19:04 +0200 |
| commit | 6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e (patch) | |
| tree | 021cc9f6b477146fcebe6f3be4752abfa2ba18a9 /drivers/video/omap2/dss/apply.c | |
| parent | 682968e0c425c60f0dde37977e5beb2b12ddc4cc (diff) | |
| parent | a385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff) | |
Merge branch 'perf/core' into perf/uprobes
Merge in latest upstream (and the latest perf development tree),
to prepare for tooling changes, and also to pick up v3.4 MM
changes that the uprobes code needs to take care of.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/video/omap2/dss/apply.c')
| -rw-r--r-- | drivers/video/omap2/dss/apply.c | 275 |
1 files changed, 221 insertions, 54 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 87b3e25294cf..b10b3bc1931e 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -105,6 +105,9 @@ static struct { struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS]; struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; + bool fifo_merge_dirty; + bool fifo_merge; + bool irq_enabled; } dss_data; @@ -351,6 +354,7 @@ static void wait_pending_extra_info_updates(void) bool updating; unsigned long flags; unsigned long t; + int r; spin_lock_irqsave(&data_lock, flags); @@ -366,11 +370,11 @@ static void wait_pending_extra_info_updates(void) spin_unlock_irqrestore(&data_lock, flags); t = msecs_to_jiffies(500); - wait_for_completion_timeout(&extra_updated_completion, t); - - updating = extra_info_update_ongoing(); - - WARN_ON(updating); + r = wait_for_completion_timeout(&extra_updated_completion, t); + if (r == 0) + DSSWARN("timeout in wait_pending_extra_info_updates\n"); + else if (r < 0) + DSSERR("wait_pending_extra_info_updates failed: %d\n", r); } int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) @@ -388,6 +392,10 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) if (mgr_manual_update(mgr)) return 0; + r = dispc_runtime_get(); + if (r) + return r; + irq = dispc_mgr_get_vsync_irq(mgr->id); mp = get_mgr_priv(mgr); @@ -428,6 +436,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) } } + dispc_runtime_put(); + return r; } @@ -451,6 +461,10 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) if (ovl_manual_update(ovl)) return 0; + r = dispc_runtime_get(); + if (r) + return r; + irq = dispc_mgr_get_vsync_irq(ovl->manager->id); op = get_ovl_priv(ovl); @@ -491,6 +505,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) } } + dispc_runtime_put(); + return r; } @@ -585,11 +601,40 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) } } +static void dss_write_regs_common(void) +{ + const int num_mgrs = omap_dss_get_num_overlay_managers(); + int i; + + if (!dss_data.fifo_merge_dirty) + return; + + for (i = 0; i < num_mgrs; ++i) { + struct omap_overlay_manager *mgr; + struct mgr_priv_data *mp; + + mgr = omap_dss_get_overlay_manager(i); + mp = get_mgr_priv(mgr); + + if (mp->enabled) { + if (dss_data.fifo_merge_dirty) { + dispc_enable_fifomerge(dss_data.fifo_merge); + dss_data.fifo_merge_dirty = false; + } + + if (mp->updating) + mp->shadow_info_dirty = true; + } + } +} + static void dss_write_regs(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); int i; + dss_write_regs_common(); + for (i = 0; i < num_mgrs; ++i) { struct omap_overlay_manager *mgr; struct mgr_priv_data *mp; @@ -640,6 +685,22 @@ static void dss_set_go_bits(void) } +static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) +{ + struct omap_overlay *ovl; + struct mgr_priv_data *mp; + struct ovl_priv_data *op; + + mp = get_mgr_priv(mgr); + mp->shadow_info_dirty = false; + + list_for_each_entry(ovl, &mgr->overlays, list) { + op = get_ovl_priv(ovl); + op->shadow_info_dirty = false; + op->shadow_extra_info_dirty = false; + } +} + void dss_mgr_start_update(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); @@ -659,6 +720,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) dss_mgr_write_regs(mgr); + dss_write_regs_common(); + mp->updating = true; if (!dss_data.irq_enabled && need_isr()) @@ -666,6 +729,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) dispc_mgr_enable(mgr->id, true); + mgr_clear_shadow_dirty(mgr); + spin_unlock_irqrestore(&data_lock, flags); } @@ -709,22 +774,6 @@ static void dss_unregister_vsync_isr(void) dss_data.irq_enabled = false; } -static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) -{ - struct omap_overlay *ovl; - struct mgr_priv_data *mp; - struct ovl_priv_data *op; - - mp = get_mgr_priv(mgr); - mp->shadow_info_dirty = false; - - list_for_each_entry(ovl, &mgr->overlays, list) { - op = get_ovl_priv(ovl); - op->shadow_info_dirty = false; - op->shadow_extra_info_dirty = false; - } -} - static void dss_apply_irq_handler(void *data, u32 mask) { const int num_mgrs = dss_feat_get_num_mgrs(); @@ -754,9 +803,6 @@ static void dss_apply_irq_handler(void *data, u32 mask) if (was_busy && !mp->busy) mgr_clear_shadow_dirty(mgr); - } else { - if (was_updating && !mp->updating) - mgr_clear_shadow_dirty(mgr); } } @@ -859,11 +905,20 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl, op->extra_info_dirty = true; } -static void dss_ovl_setup_fifo(struct omap_overlay *ovl) +static void dss_apply_fifo_merge(bool use_fifo_merge) +{ + if (dss_data.fifo_merge == use_fifo_merge) + return; + + dss_data.fifo_merge = use_fifo_merge; + dss_data.fifo_merge_dirty = true; +} + +static void dss_ovl_setup_fifo(struct omap_overlay *ovl, + bool use_fifo_merge) { struct ovl_priv_data *op = get_ovl_priv(ovl); struct omap_dss_device *dssdev; - u32 size, burst_size; u32 fifo_low, fifo_high; if (!op->enabled && !op->enabling) @@ -871,33 +926,14 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl) dssdev = ovl->manager->device; - size = dispc_ovl_get_fifo_size(ovl->id); - - burst_size = dispc_ovl_get_burst_size(ovl->id); - - switch (dssdev->type) { - case OMAP_DISPLAY_TYPE_DPI: - case OMAP_DISPLAY_TYPE_DBI: - case OMAP_DISPLAY_TYPE_SDI: - case OMAP_DISPLAY_TYPE_VENC: - case OMAP_DISPLAY_TYPE_HDMI: - default_get_overlay_fifo_thresholds(ovl->id, size, - burst_size, &fifo_low, &fifo_high); - break; -#ifdef CONFIG_OMAP2_DSS_DSI - case OMAP_DISPLAY_TYPE_DSI: - dsi_get_overlay_fifo_thresholds(ovl->id, size, - burst_size, &fifo_low, &fifo_high); - break; -#endif - default: - BUG(); - } + dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, + use_fifo_merge); dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); } -static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) +static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr, + bool use_fifo_merge) { struct omap_overlay *ovl; struct mgr_priv_data *mp; @@ -908,19 +944,94 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) return; list_for_each_entry(ovl, &mgr->overlays, list) - dss_ovl_setup_fifo(ovl); + dss_ovl_setup_fifo(ovl, use_fifo_merge); +} + +static void dss_setup_fifos(bool use_fifo_merge) +{ + const int num_mgrs = omap_dss_get_num_overlay_managers(); + struct omap_overlay_manager *mgr; + int i; + + for (i = 0; i < num_mgrs; ++i) { + mgr = omap_dss_get_overlay_manager(i); + dss_mgr_setup_fifos(mgr, use_fifo_merge); + } } -static void dss_setup_fifos(void) +static int get_num_used_managers(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); struct omap_overlay_manager *mgr; + struct mgr_priv_data *mp; int i; + int enabled_mgrs; + + enabled_mgrs = 0; for (i = 0; i < num_mgrs; ++i) { mgr = omap_dss_get_overlay_manager(i); - dss_mgr_setup_fifos(mgr); + mp = get_mgr_priv(mgr); + + if (!mp->enabled) + continue; + + enabled_mgrs++; + } + + return enabled_mgrs; +} + +static int get_num_used_overlays(void) +{ + const int num_ovls = omap_dss_get_num_overlays(); + struct omap_overlay *ovl; + struct ovl_priv_data *op; + struct mgr_priv_data *mp; + int i; + int enabled_ovls; + + enabled_ovls = 0; + + for (i = 0; i < num_ovls; ++i) { + ovl = omap_dss_get_overlay(i); + op = get_ovl_priv(ovl); + + if (!op->enabled && !op->enabling) + continue; + + mp = get_mgr_priv(ovl->manager); + + if (!mp->enabled) + continue; + + enabled_ovls++; } + + return enabled_ovls; +} + +static bool get_use_fifo_merge(void) +{ + int enabled_mgrs = get_num_used_managers(); + int enabled_ovls = get_num_used_overlays(); + + if (!dss_has_feature(FEAT_FIFO_MERGE)) + return false; + + /* + * In theory the only requirement for fifomerge is enabled_ovls <= 1. + * However, if we have two managers enabled and set/unset the fifomerge, + * we need to set the GO bits in particular sequence for the managers, + * and wait in between. + * + * This is rather difficult as new apply calls can happen at any time, + * so we simplify the problem by requiring also that enabled_mgrs <= 1. + * In practice this shouldn't matter, because when only one overlay is + * enabled, most likely only one output is enabled. + */ + + return enabled_mgrs <= 1 && enabled_ovls <= 1; } int dss_mgr_enable(struct omap_overlay_manager *mgr) @@ -928,6 +1039,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr) struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; int r; + bool fifo_merge; mutex_lock(&apply_lock); @@ -945,11 +1057,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr) goto err; } - dss_setup_fifos(); + /* step 1: setup fifos/fifomerge before enabling the manager */ + + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); dss_write_regs(); dss_set_go_bits(); + spin_unlock_irqrestore(&data_lock, flags); + + /* wait until fifo config is in */ + wait_pending_extra_info_updates(); + + /* step 2: enable the manager */ + spin_lock_irqsave(&data_lock, flags); + if (!mgr_manual_update(mgr)) mp->updating = true; @@ -974,6 +1098,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; + bool fifo_merge; mutex_lock(&apply_lock); @@ -988,8 +1113,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr) mp->updating = false; mp->enabled = false; + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); + + dss_write_regs(); + dss_set_go_bits(); + spin_unlock_irqrestore(&data_lock, flags); + wait_pending_extra_info_updates(); out: mutex_unlock(&apply_lock); } @@ -1241,6 +1374,7 @@ int dss_ovl_enable(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; + bool fifo_merge; int r; mutex_lock(&apply_lock); @@ -1266,7 +1400,22 @@ int dss_ovl_enable(struct omap_overlay *ovl) goto err2; } - dss_setup_fifos(); + /* step 1: configure fifos/fifomerge for currently enabled ovls */ + + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); + + dss_write_regs(); + dss_set_go_bits(); + + spin_unlock_irqrestore(&data_lock, flags); + + /* wait for fifo configs to go in */ + wait_pending_extra_info_updates(); + + /* step 2: enable the overlay */ + spin_lock_irqsave(&data_lock, flags); op->enabling = false; dss_apply_ovl_enable(ovl, true); @@ -1294,6 +1443,7 @@ int dss_ovl_disable(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; + bool fifo_merge; int r; mutex_lock(&apply_lock); @@ -1308,9 +1458,11 @@ int dss_ovl_disable(struct omap_overlay *ovl) goto err; } + /* step 1: disable the overlay */ spin_lock_irqsave(&data_lock, flags); dss_apply_ovl_enable(ovl, false); + dss_write_regs(); dss_set_go_bits(); @@ -1319,6 +1471,21 @@ int dss_ovl_disable(struct omap_overlay *ovl) /* wait for the overlay to be disabled */ wait_pending_extra_info_updates(); + /* step 2: configure fifos/fifomerge */ + spin_lock_irqsave(&data_lock, flags); + + fifo_merge = get_use_fifo_merge(); + dss_setup_fifos(fifo_merge); + dss_apply_fifo_merge(fifo_merge); + + dss_write_regs(); + dss_set_go_bits(); + + spin_unlock_irqrestore(&data_lock, flags); + + /* wait for fifo config to go in */ + wait_pending_extra_info_updates(); + mutex_unlock(&apply_lock); return 0; |
