Commit 4841da51 authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915: Compute proper intermediate wms for vlv/cvh



Since the watermark registers arent double buffered on VLV/CHV, we'll
need to play around with intermediate watermarks same was as we do on
ILK-BDW.

The watermark registers on VLV/CHV contain inverted values, so to find
the intermediate watermark value we just take the minimum of the
active and optimal values. This also means that, unlike ILK-BDW,
there's no chance that we'd fail to find a working intermediate
watermarks. As long as both the active and optimal watermarks are valid
the intermediate watermarks will come out valid as well.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170302171508.1666-10-ville.syrjala@linux.intel.com
parent 236c48e6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -538,6 +538,8 @@ struct intel_crtc_wm_state {
		struct {
			/* "raw" watermarks (not inverted) */
			struct vlv_pipe_wm raw[NUM_VLV_WM_LEVELS];
			/* intermediate watermarks (inverted) */
			struct vlv_wm_state intermediate;
			/* optimal watermarks (inverted) */
			struct vlv_wm_state optimal;
			/* display FIFO split */
+58 −1
Original line number Diff line number Diff line
@@ -1401,6 +1401,45 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,

#undef VLV_FIFO

static int vlv_compute_intermediate_wm(struct drm_device *dev,
				       struct intel_crtc *crtc,
				       struct intel_crtc_state *crtc_state)
{
	struct vlv_wm_state *intermediate = &crtc_state->wm.vlv.intermediate;
	const struct vlv_wm_state *optimal = &crtc_state->wm.vlv.optimal;
	const struct vlv_wm_state *active = &crtc->wm.active.vlv;
	int level;

	intermediate->num_levels = min(optimal->num_levels, active->num_levels);
	intermediate->cxsr = optimal->cxsr & active->cxsr;

	for (level = 0; level < intermediate->num_levels; level++) {
		enum plane_id plane_id;

		for_each_plane_id_on_crtc(crtc, plane_id) {
			intermediate->wm[level].plane[plane_id] =
				min(optimal->wm[level].plane[plane_id],
				    active->wm[level].plane[plane_id]);
		}

		intermediate->sr[level].plane = min(optimal->sr[level].plane,
						    active->sr[level].plane);
		intermediate->sr[level].cursor = min(optimal->sr[level].cursor,
						     active->sr[level].cursor);
	}

	vlv_invalidate_wms(crtc, intermediate, level);

	/*
	 * If our intermediate WM are identical to the final WM, then we can
	 * omit the post-vblank programming; only update if it's different.
	 */
	if (memcmp(intermediate, optimal, sizeof(*intermediate)) == 0)
		crtc_state->wm.need_postvbl_update = false;

	return 0;
}

static void vlv_merge_wm(struct drm_i915_private *dev_priv,
			 struct vlv_wm_values *wm)
{
@@ -1494,7 +1533,22 @@ static void vlv_initial_watermarks(struct intel_atomic_state *state,
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);

	mutex_lock(&dev_priv->wm.wm_mutex);
	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
	crtc->wm.active.vlv = crtc_state->wm.vlv.intermediate;
	vlv_program_watermarks(dev_priv);
	mutex_unlock(&dev_priv->wm.wm_mutex);
}

static void vlv_optimize_watermarks(struct intel_atomic_state *state,
				    struct intel_crtc_state *crtc_state)
{
	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);

	if (!crtc_state->wm.need_postvbl_update)
		return;

	mutex_lock(&dev_priv->wm.wm_mutex);
	intel_crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
	vlv_program_watermarks(dev_priv);
	mutex_unlock(&dev_priv->wm.wm_mutex);
}
@@ -4695,6 +4749,7 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
		vlv_invalidate_wms(crtc, active, level);

		crtc_state->wm.vlv.optimal = *active;
		crtc_state->wm.vlv.intermediate = *active;

		DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n",
			      pipe_name(pipe),
@@ -7861,7 +7916,9 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
		vlv_setup_wm_latency(dev_priv);
		dev_priv->display.compute_pipe_wm = vlv_compute_pipe_wm;
		dev_priv->display.compute_intermediate_wm = vlv_compute_intermediate_wm;
		dev_priv->display.initial_watermarks = vlv_initial_watermarks;
		dev_priv->display.optimize_watermarks = vlv_optimize_watermarks;
		dev_priv->display.atomic_update_watermarks = vlv_atomic_update_fifo;
	} else if (IS_PINEVIEW(dev_priv)) {
		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),