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: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Matt Roper 2015-09-24 15:53:12 -07:00 committed by Daniel Vetter
parent 3a05f5e2e7
commit 7809e5ae35
4 changed files with 48 additions and 30 deletions

View File

@ -94,6 +94,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
__drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base); __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
crtc_state->update_pipe = false; crtc_state->update_pipe = false;
crtc_state->disable_lp_wm = false;
return &crtc_state->base; return &crtc_state->base;
} }

View File

@ -11574,18 +11574,32 @@ retry:
static bool intel_wm_need_update(struct drm_plane *plane, static bool intel_wm_need_update(struct drm_plane *plane,
struct drm_plane_state *state) 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 || if (!plane->state->fb || !state->fb ||
plane->state->fb->modifier[0] != state->fb->modifier[0] || plane->state->fb->modifier[0] != state->fb->modifier[0] ||
plane->state->rotation != state->rotation) plane->state->rotation != state->rotation ||
return true; drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
if (plane->state->crtc_w != state->crtc_w) drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
return true; return true;
return false; 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, int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
struct drm_plane_state *plane_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 mode_changed = needs_modeset(crtc_state);
bool was_crtc_enabled = crtc->state->active; bool was_crtc_enabled = crtc->state->active;
bool is_crtc_enabled = crtc_state->active; bool is_crtc_enabled = crtc_state->active;
bool turn_off, turn_on, visible, was_visible; bool turn_off, turn_on, visible, was_visible;
struct drm_framebuffer *fb = plane_state->fb; 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: case DRM_PLANE_TYPE_CURSOR:
break; break;
case DRM_PLANE_TYPE_OVERLAY: 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.wait_vblank = true;
intel_crtc->atomic.update_sprite_watermarks |= intel_crtc->atomic.update_sprite_watermarks |=
1 << i; 1 << i;
} }
break;
} }
return 0; return 0;
} }

View File

@ -466,6 +466,9 @@ struct intel_crtc_state {
/* w/a for waiting 2 vblanks during crtc enable */ /* w/a for waiting 2 vblanks during crtc enable */
enum pipe hsw_workaround_pipe; enum pipe hsw_workaround_pipe;
/* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
bool disable_lp_wm;
}; };
struct vlv_wm_state { struct vlv_wm_state {

View File

@ -3730,6 +3730,18 @@ static void ilk_update_wm(struct drm_crtc *crtc)
WARN_ON(cstate->base.active != intel_crtc->active); 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); intel_compute_pipe_wm(cstate, &pipe_wm);
if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(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); 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, static void skl_pipe_wm_active_state(uint32_t val,
struct skl_pipe_wm *active, struct skl_pipe_wm *active,
bool is_transwm, bool is_transwm,
@ -7108,7 +7098,6 @@ void intel_init_pm(struct drm_device *dev)
(!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] && (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_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_wm = ilk_update_wm;
dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
} else { } else {
DRM_DEBUG_KMS("Failed to read display plane latency. " DRM_DEBUG_KMS("Failed to read display plane latency. "
"Disable CxSR\n"); "Disable CxSR\n");