drm/i915: Calculate max watermark levels for ILK+

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>
This commit is contained in:
Ville Syrjälä 2013-08-07 13:28:19 +03:00 committed by Daniel Vetter
parent 1fd527cc34
commit 158ae64f82

View File

@ -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,