From e6b0f884520e604408ebda3b60605cabe0a8d162 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:24:04 +0200 Subject: [PATCH 1/6] OMAPDSS: FEAT: Add FIFO_MERGE feature Add feature flag for fifo merge. OMAP2 doesn't contain fifo merge, later OMAPs do. dispc_enable_fifomerge() checks for the flag when called, and gives a WARN if fifo merge is being enabled when it is not supported. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 5 +++++ drivers/video/omap2/dss/dss_features.c | 9 +++++---- drivers/video/omap2/dss/dss_features.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a5ec7f37c185..d711518f9f18 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1054,6 +1054,11 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) void dispc_enable_fifomerge(bool enable) { + if (!dss_has_feature(FEAT_FIFO_MERGE)) { + WARN_ON(enable); + return; + } + DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); } diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index afcb59301c37..c2456c5bcd35 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -370,7 +370,7 @@ static const struct omap_dss_features omap3430_dss_features = { FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, .num_mgrs = 2, .num_ovls = 3, @@ -394,7 +394,7 @@ static const struct omap_dss_features omap3630_dss_features = { FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, .num_mgrs = 2, .num_ovls = 3, @@ -419,7 +419,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V | - FEAT_ALPHA_FREE_ZORDER, + FEAT_ALPHA_FREE_ZORDER | FEAT_FIFO_MERGE, .num_mgrs = 3, .num_ovls = 4, @@ -443,7 +443,8 @@ static const struct omap_dss_features omap4_dss_features = { FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | - FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER, + FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER | + FEAT_FIFO_MERGE, .num_mgrs = 3, .num_ovls = 4, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index cd833bbaac3d..50caee9192a2 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -58,6 +58,7 @@ enum dss_feat_id { FEAT_FIR_COEF_V = 1 << 25, FEAT_ALPHA_FIXED_ZORDER = 1 << 26, FEAT_ALPHA_FREE_ZORDER = 1 << 27, + FEAT_FIFO_MERGE = 1 << 28, }; /* DSS register field id */ From fb0119742291b6f30cd97026ee137b2d3d1f4de8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 16 Nov 2011 15:00:22 +0200 Subject: [PATCH 2/6] OMAPDSS: APPLY: add fifo merge support funcs Add mechanism to set/unset the DISPC fifo-merge: Add new fields to dss_data, fifo_merge and fifo_merge_dirty. These are similar to the other info/dirty flags in ovl_priv_data and ovl_mgr_data, but fifo merge is a common attribute to all managers and thus outside the ovl_mgr_data. The fifo-merge field is used in the dss_write_regs_common, which handles writing the register. dss_apply_fifo_merge() can be used to set/unset the fifo merge field in the dss_data. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/apply.c | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 052dc874cd3d..604737f1187d 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; @@ -585,11 +588,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; @@ -659,6 +691,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()) @@ -859,6 +893,15 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl, op->extra_info_dirty = true; } +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) { struct ovl_priv_data *op = get_ovl_priv(ovl); From 1d71f42b35ed66d90a9a39bc515bb16cfe2d4a46 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 16 Nov 2011 16:44:08 +0200 Subject: [PATCH 3/6] OMAPDSS: APPLY: add fifo-merge support Add fifo-merge support. This is done mainly in four functions: mgr_enable/disable and ovl_enable/disable. These are the functions where overlays are taken into and out of active use. The process to enable and disable fifo-merge is not simple. We need to do it in steps, waiting in between for certain settings to be taken into use, and continuing after that. The reason for this is that fifo-merge is a common thing for all managers/overlays, and its use must be synchronized. As an example, when we disable an overlay, we first set the overlay as disabled, then wait until the overlay is actually disabled in the HW, and only after that we may re-configure the fifos, possibly taking fifo-merge into use. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/apply.c | 164 ++++++++++++++++++++++++++++++-- 1 file changed, 156 insertions(+), 8 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 604737f1187d..6f7b213e096e 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -902,7 +902,8 @@ static void dss_apply_fifo_merge(bool use_fifo_merge) dss_data.fifo_merge_dirty = true; } -static void dss_ovl_setup_fifo(struct omap_overlay *ovl) +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; @@ -914,7 +915,16 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl) dssdev = ovl->manager->device; - size = dispc_ovl_get_fifo_size(ovl->id); + if (use_fifo_merge) { + int i; + + size = 0; + + for (i = 0; i < omap_dss_get_num_overlays(); ++i) + size += dispc_ovl_get_fifo_size(i); + } else { + size = dispc_ovl_get_fifo_size(ovl->id); + } burst_size = dispc_ovl_get_burst_size(ovl->id); @@ -940,7 +950,8 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl) 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; @@ -951,10 +962,10 @@ 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(void) +static void dss_setup_fifos(bool use_fifo_merge) { const int num_mgrs = omap_dss_get_num_overlay_managers(); struct omap_overlay_manager *mgr; @@ -962,15 +973,91 @@ static void dss_setup_fifos(void) for (i = 0; i < num_mgrs; ++i) { mgr = omap_dss_get_overlay_manager(i); - dss_mgr_setup_fifos(mgr); + dss_mgr_setup_fifos(mgr, use_fifo_merge); } } +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); + 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) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; int r; + bool fifo_merge; mutex_lock(&apply_lock); @@ -988,11 +1075,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; @@ -1017,6 +1116,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); @@ -1031,8 +1131,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); } @@ -1284,6 +1392,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); @@ -1309,7 +1418,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); @@ -1319,6 +1443,9 @@ int dss_ovl_enable(struct omap_overlay *ovl) spin_unlock_irqrestore(&data_lock, flags); + /* wait for overlay to be enabled */ + wait_pending_extra_info_updates(); + mutex_unlock(&apply_lock); return 0; @@ -1334,6 +1461,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); @@ -1348,14 +1476,34 @@ 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(); spin_unlock_irqrestore(&data_lock, flags); + /* 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; From 3cb5d966e233167fcbeb7c7d7a66294e13ee9d90 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:14:57 +0200 Subject: [PATCH 4/6] OMAPDSS: DISPC: print fifo threshold values in bytes Fifo thresholds are calculated using bytes, but the debug print prints values in buffer units. Change the prints to use bytes to be in line with the calculations, and also to print in the same units on all OMAPs. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index d711518f9f18..ba907bd60099 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1039,13 +1039,13 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); - DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", + DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n", plane, REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), - lo_start, lo_end), + lo_start, lo_end) * unit, REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), - hi_start, hi_end), - low, high); + hi_start, hi_end) * unit, + low * unit, high * unit); dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), FLD_VAL(high, hi_start, hi_end) | From 83fa2f2e940dc21a204cff697d84d37214a91708 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:17:01 +0200 Subject: [PATCH 5/6] OMAPDSS: DISPC: move fifo threhold calc to dispc.c Move fifo threshold calculation into dispc.c, as the thresholds are really dispc internal thing. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/apply.c | 34 ++----------------------------- drivers/video/omap2/dss/dispc.c | 22 ++++++++++++++++++-- drivers/video/omap2/dss/display.c | 10 --------- drivers/video/omap2/dss/dsi.c | 8 -------- drivers/video/omap2/dss/dss.h | 10 ++------- 5 files changed, 24 insertions(+), 60 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 6f7b213e096e..b0264a164652 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -907,7 +907,6 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, { 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) @@ -915,37 +914,8 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, dssdev = ovl->manager->device; - if (use_fifo_merge) { - int i; - - size = 0; - - for (i = 0; i < omap_dss_get_num_overlays(); ++i) - size += dispc_ovl_get_fifo_size(i); - } else { - 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); } diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ba907bd60099..a75972250a20 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -909,7 +909,7 @@ static void dispc_configure_burst_sizes(void) dispc_ovl_set_burst_size(i, burst_size); } -u32 dispc_ovl_get_burst_size(enum omap_plane plane) +static u32 dispc_ovl_get_burst_size(enum omap_plane plane) { unsigned unit = dss_feat_get_burst_size_unit(); /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ @@ -1018,7 +1018,7 @@ static void dispc_read_plane_fifo_sizes(void) } } -u32 dispc_ovl_get_fifo_size(enum omap_plane plane) +static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) { return dispc.fifo_size[plane]; } @@ -1063,6 +1063,24 @@ void dispc_enable_fifomerge(bool enable) REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); } +void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, + u32 *fifo_low, u32 *fifo_high, bool use_fifomerge) +{ + /* + * All sizes are in bytes. Both the buffer and burst are made of + * buffer_units, and the fifo thresholds must be buffer_unit aligned. + */ + + unsigned buf_unit = dss_feat_get_buffer_size_unit(); + unsigned fifo_size, burst_size; + + burst_size = dispc_ovl_get_burst_size(plane); + fifo_size = dispc_ovl_get_fifo_size(plane); + + *fifo_low = fifo_size - burst_size; + *fifo_high = fifo_size - buf_unit; +} + static void dispc_ovl_set_fir(enum omap_plane plane, int hinc, int vinc, enum omap_color_component color_comp) diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index be331dc5a61b..4424c198dbcd 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -279,16 +279,6 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev, } EXPORT_SYMBOL(omapdss_default_get_resolution); -void default_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high) -{ - unsigned buf_unit = dss_feat_get_buffer_size_unit(); - - *fifo_high = fifo_size - buf_unit; - *fifo_low = fifo_size - burst_size; -} - int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) { switch (dssdev->type) { diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index d4d676c82c12..a4b9d58e8b46 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4524,14 +4524,6 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) } EXPORT_SYMBOL(omapdss_dsi_enable_te); -void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high) -{ - *fifo_high = fifo_size - burst_size; - *fifo_low = fifo_size - burst_size * 2; -} - int dsi_init_display(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 32ff69fb3333..d4b3dff2ead3 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -202,9 +202,6 @@ void dss_uninit_device(struct platform_device *pdev, struct omap_dss_device *dssdev); bool dss_use_replication(struct omap_dss_device *dssdev, enum omap_color_mode mode); -void default_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high); /* manager */ int dss_init_overlay_managers(struct platform_device *pdev); @@ -313,9 +310,6 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, bool enable_hsdiv); void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); -void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, - u32 fifo_size, u32 burst_size, - u32 *fifo_low, u32 *fifo_high); void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); struct platform_device *dsi_get_dsidev_from_id(int module); @@ -429,8 +423,8 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); -u32 dispc_ovl_get_fifo_size(enum omap_plane plane); -u32 dispc_ovl_get_burst_size(enum omap_plane plane); +void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, + u32 *fifo_low, u32 *fifo_high, bool use_fifomerge); int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, bool ilace, bool replication); int dispc_ovl_enable(enum omap_plane plane, bool enable); From e0e405b9252e5e8926786d796e0d4293bc90cd56 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 13 Jan 2012 13:18:11 +0200 Subject: [PATCH 6/6] OMAPDSS: DISPC: Add naive threshold calc for fifomerge Take fifo merge into use by implementing a rather naive fifo merge threshold calculation: keep the low threshold always the same, but increase the high threshold when fifo merge is used. This should greatly increase the time between pixel data fetches from SDRAM, as the usable fifo size is much larger. However, it probably won't help for fifo underflows, as the low threshols is kept the same. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 28 ++++++++++++++++++++++---- drivers/video/omap2/dss/dss_features.c | 6 ++++-- drivers/video/omap2/dss/dss_features.h | 2 ++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a75972250a20..374c987038ac 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1072,13 +1072,33 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, */ unsigned buf_unit = dss_feat_get_buffer_size_unit(); - unsigned fifo_size, burst_size; + unsigned ovl_fifo_size, total_fifo_size, burst_size; + int i; burst_size = dispc_ovl_get_burst_size(plane); - fifo_size = dispc_ovl_get_fifo_size(plane); + ovl_fifo_size = dispc_ovl_get_fifo_size(plane); - *fifo_low = fifo_size - burst_size; - *fifo_high = fifo_size - buf_unit; + if (use_fifomerge) { + total_fifo_size = 0; + for (i = 0; i < omap_dss_get_num_overlays(); ++i) + total_fifo_size += dispc_ovl_get_fifo_size(i); + } else { + total_fifo_size = ovl_fifo_size; + } + + /* + * We use the same low threshold for both fifomerge and non-fifomerge + * cases, but for fifomerge we calculate the high threshold using the + * combined fifo size + */ + + if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { + *fifo_low = ovl_fifo_size - burst_size * 2; + *fifo_high = total_fifo_size - burst_size; + } else { + *fifo_low = ovl_fifo_size - burst_size; + *fifo_high = total_fifo_size - buf_unit; + } } static void dispc_ovl_set_fir(enum omap_plane plane, diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index c2456c5bcd35..419419ad0493 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -370,7 +370,8 @@ static const struct omap_dss_features omap3430_dss_features = { FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE | + FEAT_OMAP3_DSI_FIFO_BUG, .num_mgrs = 2, .num_ovls = 3, @@ -394,7 +395,8 @@ static const struct omap_dss_features omap3630_dss_features = { FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE, + FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER | FEAT_FIFO_MERGE | + FEAT_OMAP3_DSI_FIFO_BUG, .num_mgrs = 2, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 50caee9192a2..5f9b82156778 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -59,6 +59,8 @@ enum dss_feat_id { FEAT_ALPHA_FIXED_ZORDER = 1 << 26, FEAT_ALPHA_FREE_ZORDER = 1 << 27, FEAT_FIFO_MERGE = 1 << 28, + /* An unknown HW bug causing the normal FIFO thresholds not to work */ + FEAT_OMAP3_DSI_FIFO_BUG = 1 << 29, }; /* DSS register field id */