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

Commit 7809e5ae authored by Matt Roper's avatar Matt Roper Committed by Daniel Vetter
Browse files

drm/i915/ivb: Move WaCxSRDisabledForSpriteScaling w/a to atomic check



Determine whether we need to apply this workaround at atomic check time
and just set a flag that will be used by the main watermark update
routine.

Moving this workaround into the atomic framework reduces
ilk_update_sprite_wm() to just a standard watermark update, so drop it
completely and just ensure that ilk_update_wm() is called whenever a
sprite plane is updated in a way that would affect watermarks.

Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Reviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 3a05f5e2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
	__drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);

	crtc_state->update_pipe = false;
	crtc_state->disable_lp_wm = false;

	return &crtc_state->base;
}
+32 −7
Original line number Diff line number Diff line
@@ -11574,18 +11574,32 @@ retry:
static bool intel_wm_need_update(struct drm_plane *plane,
				 struct drm_plane_state *state)
{
	/* Update watermarks on tiling changes. */
	struct intel_plane_state *new = to_intel_plane_state(state);
	struct intel_plane_state *cur = to_intel_plane_state(plane->state);

	/* Update watermarks on tiling or size changes. */
	if (!plane->state->fb || !state->fb ||
	    plane->state->fb->modifier[0] != state->fb->modifier[0] ||
	    plane->state->rotation != state->rotation)
		return true;

	if (plane->state->crtc_w != state->crtc_w)
	    plane->state->rotation != state->rotation ||
	    drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
	    drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
	    drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
	    drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
		return true;

	return false;
}

static bool needs_scaling(struct intel_plane_state *state)
{
	int src_w = drm_rect_width(&state->src) >> 16;
	int src_h = drm_rect_height(&state->src) >> 16;
	int dst_w = drm_rect_width(&state->dst);
	int dst_h = drm_rect_height(&state->dst);

	return (src_w != dst_w || src_h != dst_h);
}

int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
				    struct drm_plane_state *plane_state)
{
@@ -11601,7 +11615,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
	bool mode_changed = needs_modeset(crtc_state);
	bool was_crtc_enabled = crtc->state->active;
	bool is_crtc_enabled = crtc_state->active;

	bool turn_off, turn_on, visible, was_visible;
	struct drm_framebuffer *fb = plane_state->fb;

@@ -11719,11 +11732,23 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
	case DRM_PLANE_TYPE_CURSOR:
		break;
	case DRM_PLANE_TYPE_OVERLAY:
		if (turn_off && !mode_changed) {
		/*
		 * WaCxSRDisabledForSpriteScaling:ivb
		 *
		 * cstate->update_wm was already set above, so this flag will
		 * take effect when we commit and program watermarks.
		 */
		if (IS_IVYBRIDGE(dev) &&
		    needs_scaling(to_intel_plane_state(plane_state)) &&
		    !needs_scaling(old_plane_state)) {
			to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
		} else if (turn_off && !mode_changed) {
			intel_crtc->atomic.wait_vblank = true;
			intel_crtc->atomic.update_sprite_watermarks |=
				1 << i;
		}

		break;
	}
	return 0;
}
+3 −0
Original line number Diff line number Diff line
@@ -466,6 +466,9 @@ struct intel_crtc_state {

	/* w/a for waiting 2 vblanks during crtc enable */
	enum pipe hsw_workaround_pipe;

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

struct vlv_wm_state {
+12 −23
Original line number Diff line number Diff line
@@ -3730,6 +3730,18 @@ static void ilk_update_wm(struct drm_crtc *crtc)

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

	/*
	 * IVB workaround: must disable low power watermarks for at least
	 * one frame before enabling scaling.  LP watermarks can be re-enabled
	 * when scaling is disabled.
	 *
	 * WaCxSRDisabledForSpriteScaling:ivb
	 */
	if (cstate->disable_lp_wm) {
		ilk_disable_lp_wm(dev);
		intel_wait_for_vblank(dev, intel_crtc->pipe);
	}

	intel_compute_pipe_wm(cstate, &pipe_wm);

	if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
@@ -3761,28 +3773,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
	ilk_write_wm_values(dev_priv, &results);
}

static void
ilk_update_sprite_wm(struct drm_plane *plane,
		     struct drm_crtc *crtc,
		     uint32_t sprite_width, uint32_t sprite_height,
		     int pixel_size, bool enabled, bool scaled)
{
	struct drm_device *dev = plane->dev;
	struct intel_plane *intel_plane = to_intel_plane(plane);

	/*
	 * IVB workaround: must disable low power watermarks for at least
	 * one frame before enabling scaling.  LP watermarks can be re-enabled
	 * when scaling is disabled.
	 *
	 * WaCxSRDisabledForSpriteScaling:ivb
	 */
	if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
		intel_wait_for_vblank(dev, intel_plane->pipe);

	ilk_update_wm(crtc);
}

static void skl_pipe_wm_active_state(uint32_t val,
				     struct skl_pipe_wm *active,
				     bool is_transwm,
@@ -7108,7 +7098,6 @@ void intel_init_pm(struct drm_device *dev)
		    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
		     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
			dev_priv->display.update_wm = ilk_update_wm;
			dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
		} else {
			DRM_DEBUG_KMS("Failed to read display plane latency. "
				      "Disable CxSR\n");