From 158ae64f820939473012dacfc0ae1ec782b45b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 7 Aug 2013 13:28:19 +0300 Subject: [PATCH] drm/i915: Calculate max watermark levels for ILK+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are quite a few variables we need to take into account to determine the maximum watermark levels, so it feels a bit cleaner to calculate those rather than just have a bunch of what look like magic numbers. v2: s/pipes_active/num_pipes_active s/othwewise/otherwise Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 119 ++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d7bb61efca2d..a4c3c5497941 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2270,6 +2270,104 @@ static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params, params->pri_bytes_per_pixel); } +static unsigned int ilk_display_fifo_size(const struct drm_device *dev) +{ + if (INTEL_INFO(dev)->gen >= 7) + return 768; + else + return 512; +} + +/* Calculate the maximum primary/sprite plane watermark */ +static unsigned int ilk_plane_wm_max(const struct drm_device *dev, + int level, + unsigned int num_pipes_active, + bool sprite_enabled, + enum intel_ddb_partitioning ddb_partitioning, + bool is_sprite) +{ + unsigned int fifo_size = ilk_display_fifo_size(dev); + unsigned int max; + + /* if sprites aren't enabled, sprites get nothing */ + if (is_sprite && !sprite_enabled) + return 0; + + /* HSW allows LP1+ watermarks even with multiple pipes */ + if (level == 0 || num_pipes_active > 1) { + fifo_size /= INTEL_INFO(dev)->num_pipes; + + /* + * For some reason the non self refresh + * FIFO size is only half of the self + * refresh FIFO size on ILK/SNB. + */ + if (INTEL_INFO(dev)->gen <= 6) + fifo_size /= 2; + } + + if (sprite_enabled) { + /* level 0 is always calculated with 1:1 split */ + if (level > 0 && ddb_partitioning == INTEL_DDB_PART_5_6) { + if (is_sprite) + fifo_size *= 5; + fifo_size /= 6; + } else { + fifo_size /= 2; + } + } + + /* clamp to max that the registers can hold */ + if (INTEL_INFO(dev)->gen >= 7) + /* IVB/HSW primary/sprite plane watermarks */ + max = level == 0 ? 127 : 1023; + else if (!is_sprite) + /* ILK/SNB primary plane watermarks */ + max = level == 0 ? 127 : 511; + else + /* ILK/SNB sprite plane watermarks */ + max = level == 0 ? 63 : 255; + + return min(fifo_size, max); +} + +/* Calculate the maximum cursor plane watermark */ +static unsigned int ilk_cursor_wm_max(const struct drm_device *dev, + int level, unsigned int num_pipes_active) +{ + /* HSW LP1+ watermarks w/ multiple pipes */ + if (level > 0 && num_pipes_active > 1) + return 64; + + /* otherwise just report max that registers can hold */ + if (INTEL_INFO(dev)->gen >= 7) + return level == 0 ? 63 : 255; + else + return level == 0 ? 31 : 63; +} + +/* Calculate the maximum FBC watermark */ +static unsigned int ilk_fbc_wm_max(void) +{ + /* max that registers can hold */ + return 15; +} + +static void ilk_wm_max(struct drm_device *dev, + int level, + unsigned int num_pipes_active, + bool sprite_enabled, + enum intel_ddb_partitioning ddb_partitioning, + struct hsw_wm_maximums *max) +{ + max->pri = ilk_plane_wm_max(dev, level, num_pipes_active, + sprite_enabled, ddb_partitioning, false); + max->spr = ilk_plane_wm_max(dev, level, num_pipes_active, + sprite_enabled, ddb_partitioning, true); + max->cur = ilk_cursor_wm_max(dev, level, num_pipes_active); + max->fbc = ilk_fbc_wm_max(); +} + static bool ilk_check_wm(int level, const struct hsw_wm_maximums *max, struct intel_wm_level *result) @@ -2555,18 +2653,15 @@ static void hsw_compute_wm_parameters(struct drm_device *dev, sprites_enabled++; } - if (pipes_active > 1) { - lp_max_1_2->pri = lp_max_5_6->pri = sprites_enabled ? 128 : 256; - lp_max_1_2->spr = lp_max_5_6->spr = 128; - lp_max_1_2->cur = lp_max_5_6->cur = 64; - } else { - lp_max_1_2->pri = sprites_enabled ? 384 : 768; - lp_max_5_6->pri = sprites_enabled ? 128 : 768; - lp_max_1_2->spr = 384; - lp_max_5_6->spr = 640; - lp_max_1_2->cur = lp_max_5_6->cur = 255; - } - lp_max_1_2->fbc = lp_max_5_6->fbc = 15; + ilk_wm_max(dev, 1, pipes_active, sprites_enabled, + INTEL_DDB_PART_1_2, lp_max_1_2); + + /* 5/6 split only in single pipe config on IVB+ */ + if (INTEL_INFO(dev)->gen >= 7 && pipes_active <= 1) + ilk_wm_max(dev, 1, pipes_active, sprites_enabled, + INTEL_DDB_PART_5_6, lp_max_5_6); + else + *lp_max_5_6 = *lp_max_1_2; } static void hsw_compute_wm_results(struct drm_device *dev,