blob: ed3cbb95c4145230f90afa10e7af5700a03a5fbf [file] [log] [blame]
From de594f8178a74406d1b7947e8adeb574821c7925 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Wed, 7 Aug 2013 13:28:19 +0300
Subject: 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 <chris@chris-wilson.co.uk>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
(cherry picked from commit 158ae64f820939473012dacfc0ae1ec782b45b60)
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
---
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 d10d4c717b4a..5daa32a4e864 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,
--
1.8.5.rc3