drm/i915: Calculate watermark configuration during atomic check (v2)
v2: Don't forget to actually check the cstate->active value when tallying up the number of active CRTC's. (Ander) Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Smoke-tested-by: Paulo Zanoni <przanoni@gmail.com> Link: http://patchwork.freedesktop.org/patch/59561/
This commit is contained in:
parent
19b8d3875e
commit
aa36313686
|
@ -1692,6 +1692,13 @@ struct i915_execbuffer_params {
|
|||
struct drm_i915_gem_request *request;
|
||||
};
|
||||
|
||||
/* used in computing the new watermarks state */
|
||||
struct intel_wm_config {
|
||||
unsigned int num_pipes_active;
|
||||
bool sprites_enabled;
|
||||
bool sprites_scaled;
|
||||
};
|
||||
|
||||
struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
struct kmem_cache *objects;
|
||||
|
@ -1917,6 +1924,9 @@ struct drm_i915_private {
|
|||
*/
|
||||
uint16_t skl_latency[8];
|
||||
|
||||
/* Committed wm config */
|
||||
struct intel_wm_config config;
|
||||
|
||||
/*
|
||||
* The skl_wm_values structure is a bit too big for stack
|
||||
* allocation, so we keep the staging struct where we store
|
||||
|
|
|
@ -13050,6 +13050,45 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle calculation of various watermark data at the end of the atomic check
|
||||
* phase. The code here should be run after the per-crtc and per-plane 'check'
|
||||
* handlers to ensure that all derived state has been updated.
|
||||
*/
|
||||
static void calc_watermark_data(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = state->dev;
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *cstate;
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *pstate;
|
||||
|
||||
/*
|
||||
* Calculate watermark configuration details now that derived
|
||||
* plane/crtc state is all properly updated.
|
||||
*/
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?:
|
||||
crtc->state;
|
||||
|
||||
if (cstate->active)
|
||||
intel_state->wm_config.num_pipes_active++;
|
||||
}
|
||||
drm_for_each_legacy_plane(plane, dev) {
|
||||
pstate = drm_atomic_get_existing_plane_state(state, plane) ?:
|
||||
plane->state;
|
||||
|
||||
if (!to_intel_plane_state(pstate)->visible)
|
||||
continue;
|
||||
|
||||
intel_state->wm_config.sprites_enabled = true;
|
||||
if (pstate->crtc_w != pstate->src_w >> 16 ||
|
||||
pstate->crtc_h != pstate->src_h >> 16)
|
||||
intel_state->wm_config.sprites_scaled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_atomic_check - validate state object
|
||||
* @dev: drm device
|
||||
|
@ -13058,6 +13097,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
|
|||
static int intel_atomic_check(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int ret, i;
|
||||
|
@ -13121,10 +13161,15 @@ static int intel_atomic_check(struct drm_device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
} else
|
||||
to_intel_atomic_state(state)->cdclk =
|
||||
to_i915(state->dev)->cdclk_freq;
|
||||
intel_state->cdclk = to_i915(state->dev)->cdclk_freq;
|
||||
|
||||
return drm_atomic_helper_check_planes(state->dev, state);
|
||||
ret = drm_atomic_helper_check_planes(state->dev, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
calc_watermark_data(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13164,6 +13209,7 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|||
return ret;
|
||||
|
||||
drm_atomic_helper_swap_state(dev, state);
|
||||
dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
|
|
@ -250,6 +250,7 @@ struct intel_atomic_state {
|
|||
unsigned int cdclk;
|
||||
bool dpll_set;
|
||||
struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
|
||||
struct intel_wm_config wm_config;
|
||||
};
|
||||
|
||||
struct intel_plane_state {
|
||||
|
|
|
@ -1715,13 +1715,6 @@ struct ilk_wm_maximums {
|
|||
uint16_t fbc;
|
||||
};
|
||||
|
||||
/* used in computing the new watermarks state */
|
||||
struct intel_wm_config {
|
||||
unsigned int num_pipes_active;
|
||||
bool sprites_enabled;
|
||||
bool sprites_scaled;
|
||||
};
|
||||
|
||||
/*
|
||||
* For both WM_PIPE and WM_LP.
|
||||
* mem_value must be in 0.1us units.
|
||||
|
@ -2251,24 +2244,6 @@ static void skl_setup_wm_latency(struct drm_device *dev)
|
|||
intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
|
||||
}
|
||||
|
||||
static void ilk_compute_wm_config(struct drm_device *dev,
|
||||
struct intel_wm_config *config)
|
||||
{
|
||||
struct intel_crtc *intel_crtc;
|
||||
|
||||
/* Compute the currently _active_ config */
|
||||
for_each_intel_crtc(dev, intel_crtc) {
|
||||
const struct intel_pipe_wm *wm = &intel_crtc->wm.active.ilk;
|
||||
|
||||
if (!wm->pipe_enabled)
|
||||
continue;
|
||||
|
||||
config->sprites_enabled |= wm->sprites_enabled;
|
||||
config->sprites_scaled |= wm->sprites_scaled;
|
||||
config->num_pipes_active++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute new watermarks for the pipe */
|
||||
static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
|
||||
struct drm_atomic_state *state)
|
||||
|
@ -2917,11 +2892,12 @@ skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate)
|
|||
|
||||
static void
|
||||
skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
|
||||
const struct intel_wm_config *config,
|
||||
struct skl_ddb_allocation *ddb /* out */)
|
||||
{
|
||||
struct drm_crtc *crtc = cstate->base.crtc;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_wm_config *config = &dev_priv->wm.config;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_plane *intel_plane;
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
|
@ -3096,15 +3072,6 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void skl_compute_wm_global_parameters(struct drm_device *dev,
|
||||
struct intel_wm_config *config)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
config->num_pipes_active += to_intel_crtc(crtc)->active;
|
||||
}
|
||||
|
||||
static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
|
||||
struct intel_crtc_state *cstate,
|
||||
struct intel_plane *intel_plane,
|
||||
|
@ -3507,14 +3474,13 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
|
|||
}
|
||||
|
||||
static bool skl_update_pipe_wm(struct drm_crtc *crtc,
|
||||
struct intel_wm_config *config,
|
||||
struct skl_ddb_allocation *ddb, /* out */
|
||||
struct skl_pipe_wm *pipe_wm /* out */)
|
||||
{
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
|
||||
|
||||
skl_allocate_pipe_ddb(cstate, config, ddb);
|
||||
skl_allocate_pipe_ddb(cstate, ddb);
|
||||
skl_compute_pipe_wm(cstate, ddb, pipe_wm);
|
||||
|
||||
if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
|
||||
|
@ -3527,7 +3493,6 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
|
|||
|
||||
static void skl_update_other_pipe_wm(struct drm_device *dev,
|
||||
struct drm_crtc *crtc,
|
||||
struct intel_wm_config *config,
|
||||
struct skl_wm_values *r)
|
||||
{
|
||||
struct intel_crtc *intel_crtc;
|
||||
|
@ -3557,7 +3522,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
|
|||
if (!intel_crtc->active)
|
||||
continue;
|
||||
|
||||
wm_changed = skl_update_pipe_wm(&intel_crtc->base, config,
|
||||
wm_changed = skl_update_pipe_wm(&intel_crtc->base,
|
||||
&r->ddb, &pipe_wm);
|
||||
|
||||
/*
|
||||
|
@ -3600,7 +3565,6 @@ static void skl_update_wm(struct drm_crtc *crtc)
|
|||
struct skl_wm_values *results = &dev_priv->wm.skl_results;
|
||||
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
|
||||
struct skl_pipe_wm *pipe_wm = &cstate->wm.optimal.skl;
|
||||
struct intel_wm_config config = {};
|
||||
|
||||
|
||||
/* Clear all dirty flags */
|
||||
|
@ -3608,15 +3572,13 @@ static void skl_update_wm(struct drm_crtc *crtc)
|
|||
|
||||
skl_clear_wm(results, intel_crtc->pipe);
|
||||
|
||||
skl_compute_wm_global_parameters(dev, &config);
|
||||
|
||||
if (!skl_update_pipe_wm(crtc, &config, &results->ddb, pipe_wm))
|
||||
if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm))
|
||||
return;
|
||||
|
||||
skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
|
||||
results->dirty[intel_crtc->pipe] = true;
|
||||
|
||||
skl_update_other_pipe_wm(dev, crtc, &config, results);
|
||||
skl_update_other_pipe_wm(dev, crtc, results);
|
||||
skl_write_wm_values(dev_priv, results);
|
||||
skl_flush_wm_values(dev_priv, results);
|
||||
|
||||
|
@ -3629,20 +3591,18 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
|
||||
struct ilk_wm_maximums max;
|
||||
struct intel_wm_config config = {};
|
||||
struct intel_wm_config *config = &dev_priv->wm.config;
|
||||
struct ilk_wm_values results = {};
|
||||
enum intel_ddb_partitioning partitioning;
|
||||
|
||||
ilk_compute_wm_config(dev, &config);
|
||||
|
||||
ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
|
||||
ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
|
||||
ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_1_2, &max);
|
||||
ilk_wm_merge(dev, config, &max, &lp_wm_1_2);
|
||||
|
||||
/* 5/6 split only in single pipe config on IVB+ */
|
||||
if (INTEL_INFO(dev)->gen >= 7 &&
|
||||
config.num_pipes_active == 1 && config.sprites_enabled) {
|
||||
ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
|
||||
ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
|
||||
config->num_pipes_active == 1 && config->sprites_enabled) {
|
||||
ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_5_6, &max);
|
||||
ilk_wm_merge(dev, config, &max, &lp_wm_5_6);
|
||||
|
||||
best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue