Explorar o código

drm/i915: Sanitize VLV/CHV watermarks properly

Clear out the watermark for all disabled planes to 0. This is required
to avoid falsely thinking that the inherited watermarks are bogus in
case the watermark is actually higher than the FIFO size.

v2: s/noninverted/raw/ for consistency with other platforms

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170302171508.1666-13-ville.syrjala@linux.intel.com
Ville Syrjälä %!s(int64=8) %!d(string=hai) anos
pai
achega
602ae83550

+ 11 - 6
drivers/gpu/drm/i915/intel_display.c

@@ -3478,7 +3478,8 @@ __intel_display_resume(struct drm_device *dev,
 	}
 	}
 
 
 	/* ignore any reset values/BIOS leftovers in the WM registers */
 	/* ignore any reset values/BIOS leftovers in the WM registers */
-	to_intel_atomic_state(state)->skip_intermediate_wm = true;
+	if (!HAS_GMCH_DISPLAY(to_i915(dev)))
+		to_intel_atomic_state(state)->skip_intermediate_wm = true;
 
 
 	ret = drm_atomic_commit(state);
 	ret = drm_atomic_commit(state);
 
 
@@ -14877,7 +14878,8 @@ retry:
 	 * intermediate watermarks (since we don't trust the current
 	 * intermediate watermarks (since we don't trust the current
 	 * watermarks).
 	 * watermarks).
 	 */
 	 */
-	intel_state->skip_intermediate_wm = true;
+	if (!HAS_GMCH_DISPLAY(dev_priv))
+		intel_state->skip_intermediate_wm = true;
 
 
 	ret = intel_atomic_check(dev, state);
 	ret = intel_atomic_check(dev, state);
 	if (ret) {
 	if (ret) {
@@ -15040,7 +15042,8 @@ int intel_modeset_init(struct drm_device *dev)
 	 * Note that we need to do this after reconstructing the BIOS fb's
 	 * Note that we need to do this after reconstructing the BIOS fb's
 	 * since the watermark calculation done here will use pstate->fb.
 	 * since the watermark calculation done here will use pstate->fb.
 	 */
 	 */
-	sanitize_watermarks(dev);
+	if (!HAS_GMCH_DISPLAY(dev_priv))
+		sanitize_watermarks(dev);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -15511,12 +15514,14 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
 		pll->on = false;
 		pll->on = false;
 	}
 	}
 
 
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		vlv_wm_get_hw_state(dev);
 		vlv_wm_get_hw_state(dev);
-	else if (IS_GEN9(dev_priv))
+		vlv_wm_sanitize(dev_priv);
+	} else if (IS_GEN9(dev_priv)) {
 		skl_wm_get_hw_state(dev);
 		skl_wm_get_hw_state(dev);
-	else if (HAS_PCH_SPLIT(dev_priv))
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		ilk_wm_get_hw_state(dev);
 		ilk_wm_get_hw_state(dev);
+	}
 
 
 	for_each_intel_crtc(dev, crtc) {
 	for_each_intel_crtc(dev, crtc) {
 		u64 put_domains;
 		u64 put_domains;

+ 1 - 0
drivers/gpu/drm/i915/intel_drv.h

@@ -1824,6 +1824,7 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
 			  struct skl_ddb_allocation *ddb /* out */);
 			  struct skl_ddb_allocation *ddb /* out */);
 void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
 void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
 			      struct skl_pipe_wm *out);
 			      struct skl_pipe_wm *out);
+void vlv_wm_sanitize(struct drm_i915_private *dev_priv);
 bool intel_can_enable_sagv(struct drm_atomic_state *state);
 bool intel_can_enable_sagv(struct drm_atomic_state *state);
 int intel_enable_sagv(struct drm_i915_private *dev_priv);
 int intel_enable_sagv(struct drm_i915_private *dev_priv);
 int intel_disable_sagv(struct drm_i915_private *dev_priv);
 int intel_disable_sagv(struct drm_i915_private *dev_priv);

+ 49 - 1
drivers/gpu/drm/i915/intel_pm.c

@@ -4725,7 +4725,6 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 		active->num_levels = wm->level + 1;
 		active->num_levels = wm->level + 1;
 		active->cxsr = wm->cxsr;
 		active->cxsr = wm->cxsr;
 
 
-		/* FIXME sanitize things more */
 		for (level = 0; level < active->num_levels; level++) {
 		for (level = 0; level < active->num_levels; level++) {
 			struct vlv_pipe_wm *raw =
 			struct vlv_pipe_wm *raw =
 				&crtc_state->wm.vlv.raw[level];
 				&crtc_state->wm.vlv.raw[level];
@@ -4763,6 +4762,55 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 		      wm->sr.plane, wm->sr.cursor, wm->level, wm->cxsr);
 		      wm->sr.plane, wm->sr.cursor, wm->level, wm->cxsr);
 }
 }
 
 
+void vlv_wm_sanitize(struct drm_i915_private *dev_priv)
+{
+	struct intel_plane *plane;
+	struct intel_crtc *crtc;
+
+	mutex_lock(&dev_priv->wm.wm_mutex);
+
+	for_each_intel_plane(&dev_priv->drm, plane) {
+		struct intel_crtc *crtc =
+			intel_get_crtc_for_pipe(dev_priv, plane->pipe);
+		struct intel_crtc_state *crtc_state =
+			to_intel_crtc_state(crtc->base.state);
+		struct intel_plane_state *plane_state =
+			to_intel_plane_state(plane->base.state);
+		struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
+		const struct vlv_fifo_state *fifo_state =
+			&crtc_state->wm.vlv.fifo_state;
+		enum plane_id plane_id = plane->id;
+		int level;
+
+		if (plane_state->base.visible)
+			continue;
+
+		for (level = 0; level < wm_state->num_levels; level++) {
+			struct vlv_pipe_wm *raw =
+				&crtc_state->wm.vlv.raw[level];
+
+			raw->plane[plane_id] = 0;
+
+			wm_state->wm[level].plane[plane_id] =
+				vlv_invert_wm_value(raw->plane[plane_id],
+						    fifo_state->plane[plane_id]);
+		}
+	}
+
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
+		struct intel_crtc_state *crtc_state =
+			to_intel_crtc_state(crtc->base.state);
+
+		crtc_state->wm.vlv.intermediate =
+			crtc_state->wm.vlv.optimal;
+		crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
+	}
+
+	vlv_program_watermarks(dev_priv);
+
+	mutex_unlock(&dev_priv->wm.wm_mutex);
+}
+
 void ilk_wm_get_hw_state(struct drm_device *dev)
 void ilk_wm_get_hw_state(struct drm_device *dev)
 {
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_private *dev_priv = to_i915(dev);