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

Commit 4e0963c7 authored by Matt Roper's avatar Matt Roper
Browse files

drm/i915: Calculate pipe watermarks into CRTC state (v3)



A future patch will calculate these during the atomic 'check' phase
rather than at WM programming time, so let's store the watermark
values we're planning to use in the CRTC state; the values actually
active on the hardware remains in intel_crtc.

While we're at it, do some minor restructuring to keep ILK and SKL
values in a union.

v2: Don't move cxsr_allowed to state (Maarten)

v3: Only calculate watermarks in state.  Still keep active watermarks in
    intel_crtc itself.  (Ville)

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/59556/
parent b9d5c839
Loading
Loading
Loading
Loading
+30 −18
Original line number Diff line number Diff line
@@ -334,6 +334,21 @@ struct intel_crtc_scaler_state {
/* drm_mode->private_flags */
#define I915_MODE_FLAG_INHERITED 1

struct intel_pipe_wm {
	struct intel_wm_level wm[5];
	uint32_t linetime;
	bool fbc_wm_enabled;
	bool pipe_enabled;
	bool sprites_enabled;
	bool sprites_scaled;
};

struct skl_pipe_wm {
	struct skl_wm_level wm[8];
	struct skl_wm_level trans_wm;
	uint32_t linetime;
};

struct intel_crtc_state {
	struct drm_crtc_state base;

@@ -471,6 +486,17 @@ struct intel_crtc_state {

	/* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
	bool disable_lp_wm;

	struct {
		/*
		 * optimal watermarks, programmed post-vblank when this state
		 * is committed
		 */
		union {
			struct intel_pipe_wm ilk;
			struct skl_pipe_wm skl;
		} optimal;
	} wm;
};

struct vlv_wm_state {
@@ -482,15 +508,6 @@ struct vlv_wm_state {
	bool cxsr;
};

struct intel_pipe_wm {
	struct intel_wm_level wm[5];
	uint32_t linetime;
	bool fbc_wm_enabled;
	bool pipe_enabled;
	bool sprites_enabled;
	bool sprites_scaled;
};

struct intel_mmio_flip {
	struct work_struct work;
	struct drm_i915_private *i915;
@@ -499,12 +516,6 @@ struct intel_mmio_flip {
	unsigned int rotation;
};

struct skl_pipe_wm {
	struct skl_wm_level wm[8];
	struct skl_wm_level trans_wm;
	uint32_t linetime;
};

/*
 * Tracking of operations that need to be performed at the beginning/end of an
 * atomic commit, outside the atomic section where interrupts are disabled.
@@ -571,9 +582,10 @@ struct intel_crtc {
	/* per-pipe watermark state */
	struct {
		/* watermarks currently being used  */
		struct intel_pipe_wm active;
		/* SKL wm values currently in use */
		struct skl_pipe_wm skl_active;
		union {
			struct intel_pipe_wm ilk;
			struct skl_pipe_wm skl;
		} active;
		/* allow CxSR on this pipe */
		bool cxsr_allowed;
	} wm;
+27 −17
Original line number Diff line number Diff line
@@ -2274,7 +2274,7 @@ static void ilk_compute_wm_config(struct drm_device *dev,

	/* Compute the currently _active_ config */
	for_each_intel_crtc(dev, intel_crtc) {
		const struct intel_pipe_wm *wm = &intel_crtc->wm.active;
		const struct intel_pipe_wm *wm = &intel_crtc->wm.active.ilk;

		if (!wm->pipe_enabled)
			continue;
@@ -2371,7 +2371,9 @@ static void ilk_merge_wm_level(struct drm_device *dev,
	ret_wm->enable = true;

	for_each_intel_crtc(dev, intel_crtc) {
		const struct intel_pipe_wm *active = &intel_crtc->wm.active;
		const struct intel_crtc_state *cstate =
			to_intel_crtc_state(intel_crtc->base.state);
		const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
		const struct intel_wm_level *wm = &active->wm[level];

		if (!active->pipe_enabled)
@@ -2519,14 +2521,15 @@ static void ilk_compute_wm_results(struct drm_device *dev,

	/* LP0 register values */
	for_each_intel_crtc(dev, intel_crtc) {
		const struct intel_crtc_state *cstate =
			to_intel_crtc_state(intel_crtc->base.state);
		enum pipe pipe = intel_crtc->pipe;
		const struct intel_wm_level *r =
			&intel_crtc->wm.active.wm[0];
		const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];

		if (WARN_ON(!r->enable))
			continue;

		results->wm_linetime[pipe] = intel_crtc->wm.active.linetime;
		results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;

		results->wm_pipe[pipe] =
			(r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@@ -3511,10 +3514,10 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
	skl_allocate_pipe_ddb(cstate, config, ddb);
	skl_compute_pipe_wm(cstate, ddb, pipe_wm);

	if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
	if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
		return false;

	intel_crtc->wm.skl_active = *pipe_wm;
	intel_crtc->wm.active.skl = *pipe_wm;

	return true;
}
@@ -3592,7 +3595,8 @@ static void skl_update_wm(struct drm_crtc *crtc)
	struct drm_device *dev = crtc->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct skl_wm_values *results = &dev_priv->wm.skl_results;
	struct skl_pipe_wm pipe_wm = {};
	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 = {};


@@ -3603,10 +3607,10 @@ static void skl_update_wm(struct drm_crtc *crtc)

	skl_compute_wm_global_parameters(dev, &config);

	if (!skl_update_pipe_wm(crtc, &config, &results->ddb, &pipe_wm))
	if (!skl_update_pipe_wm(crtc, &config, &results->ddb, pipe_wm))
		return;

	skl_compute_wm_results(dev, &pipe_wm, results, intel_crtc);
	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);
@@ -3655,7 +3659,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
	struct intel_pipe_wm pipe_wm = {};

	WARN_ON(cstate->base.active != intel_crtc->active);

@@ -3671,12 +3674,13 @@ static void ilk_update_wm(struct drm_crtc *crtc)
		intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
	}

	intel_compute_pipe_wm(cstate, &pipe_wm);
	intel_compute_pipe_wm(cstate, &cstate->wm.optimal.ilk);

	if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
		return;
	if (!memcmp(&intel_crtc->wm.active.ilk,
		    &cstate->wm.optimal.ilk,
		    sizeof(cstate->wm.optimal.ilk)));

	intel_crtc->wm.active = pipe_wm;
	intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;

	ilk_program_watermarks(dev_priv);
}
@@ -3731,7 +3735,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct skl_pipe_wm *active = &intel_crtc->wm.skl_active;
	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
	struct skl_pipe_wm *active = &cstate->wm.optimal.skl;
	enum pipe pipe = intel_crtc->pipe;
	int level, i, max_level;
	uint32_t temp;
@@ -3775,6 +3780,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)

	temp = hw->plane_trans[pipe][PLANE_CURSOR];
	skl_pipe_wm_active_state(temp, active, true, true, i, 0);

	intel_crtc->wm.active.skl = *active;
}

void skl_wm_get_hw_state(struct drm_device *dev)
@@ -3794,7 +3801,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct ilk_wm_values *hw = &dev_priv->wm.hw;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_pipe_wm *active = &intel_crtc->wm.active;
	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
	struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
	enum pipe pipe = intel_crtc->pipe;
	static const unsigned int wm0_pipe_reg[] = {
		[PIPE_A] = WM0_PIPEA_ILK,
@@ -3833,6 +3841,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
		for (level = 0; level <= max_level; level++)
			active->wm[level].enable = true;
	}

	intel_crtc->wm.active.ilk = *active;
}

#define _FW_WM(value, plane) \