Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa363136 authored by Matt Roper's avatar Matt Roper
Browse files

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: default avatarMatt Roper <matthew.d.roper@intel.com>
Reviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Smoke-tested-by: default avatarPaulo Zanoni <przanoni@gmail.com>
Link: http://patchwork.freedesktop.org/patch/59561/
parent 19b8d387
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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
+49 −3
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+12 −52
Original line number Diff line number Diff line
@@ -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 {