[Intel-gfx] [RFC 09/15] drm/i915: Allow ILK watermark computation to use atomic state
Matt Roper
matthew.d.roper at intel.com
Wed May 20 19:12:21 PDT 2015
In preparation for refactoring watermark computation out to the atomic
'check' phase, we need to allow that computation to operate on the
in-flight state stored in a drm_atomic_state, rather than
already-committed CRTC and plane states (eventually the drm_atomic_state
should be the only source, but we allow both approaches at the moment as
we transition).
While we're at it, s/intel_compute_pipe_wm/ilk_compute_pipe_wm/ since
this function only applies to ILK-style watermarks and we have a
completely different function for SKL-style watermarks.
Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
---
drivers/gpu/drm/i915/intel_pm.c | 102 +++++++++++++++++++++++++---------------
1 file changed, 64 insertions(+), 38 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index dbff278..c3b9f99 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1772,9 +1772,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
const struct intel_crtc *intel_crtc,
int level,
struct intel_crtc_state *cstate,
+ struct intel_plane_state *pristate,
+ struct intel_plane_state *sprstate,
+ struct intel_plane_state *curstate,
struct intel_wm_level *result)
{
- struct intel_plane *intel_plane;
uint16_t pri_latency = dev_priv->wm.pri_latency[level];
uint16_t spr_latency = dev_priv->wm.spr_latency[level];
uint16_t cur_latency = dev_priv->wm.cur_latency[level];
@@ -1786,29 +1788,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
cur_latency *= 5;
}
- for_each_intel_plane_of_crtc(intel_crtc, intel_plane) {
- struct intel_plane_state *pstate =
- to_intel_plane_state(intel_plane->base.state);
-
- switch (intel_plane->base.type) {
- case DRM_PLANE_TYPE_PRIMARY:
- result->pri_val = ilk_compute_pri_wm(cstate, pstate,
- pri_latency,
- level);
- result->fbc_val = ilk_compute_fbc_wm(cstate, pstate,
- result->pri_val);
- break;
- case DRM_PLANE_TYPE_OVERLAY:
- result->spr_val = ilk_compute_spr_wm(cstate, pstate,
- spr_latency);
- break;
- case DRM_PLANE_TYPE_CURSOR:
- result->cur_val = ilk_compute_cur_wm(cstate, pstate,
- cur_latency);
- break;
- }
- }
-
+ result->pri_val = ilk_compute_pri_wm(cstate, pristate,
+ pri_latency, level);
+ result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
+ result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
+ result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
result->enable = true;
}
@@ -2086,15 +2070,20 @@ static void ilk_compute_wm_config(struct drm_device *dev,
}
/* Compute new watermarks for the pipe */
-static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
- struct intel_pipe_wm *pipe_wm)
+static int ilk_compute_pipe_wm(struct drm_crtc *crtc,
+ struct drm_atomic_state *state,
+ struct intel_pipe_wm *pipe_wm)
{
- struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
const struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct drm_crtc_state *cs;
+ struct intel_crtc_state *cstate = NULL;
struct intel_plane *intel_plane;
+ struct drm_plane_state *ps;
+ struct intel_plane_state *pristate = NULL;
struct intel_plane_state *sprstate = NULL;
+ struct intel_plane_state *curstate = NULL;
int level, max_level = ilk_wm_max_level(dev);
/* LP0 watermark maximums depend on this pipe alone */
struct intel_wm_config config = {
@@ -2102,11 +2091,47 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
};
struct ilk_wm_maximums max;
- for_each_intel_plane_of_crtc(intel_crtc, intel_plane) {
- if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) {
- sprstate = to_intel_plane_state(intel_plane->base.state);
- break;
+ /*
+ * FIXME: In an upcoming patch, we'll *only* be calling this from the
+ * atomic 'check' codepath and thus will always have a top-level atomic
+ * transaction. However at the moment we still call this in the legacy
+ * 'ilk_update_wm' function, which means we need to be able to also
+ * operate on already-committed state which has been detached from any
+ * top-level transaction.
+ *
+ * Drop the 'else' block here once we only do atomic-style watermarks.
+ */
+ if (state) {
+ cs = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+ else
+ cstate = to_intel_crtc_state(cs);
+
+ for_each_intel_plane_of_crtc(intel_crtc, intel_plane) {
+ ps = drm_atomic_get_plane_state(state,
+ &intel_plane->base);
+ if (IS_ERR(ps))
+ return PTR_ERR(ps);
+
+ if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+ pristate = to_intel_plane_state(ps);
+ else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY)
+ sprstate = to_intel_plane_state(ps);
+ else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
+ curstate = to_intel_plane_state(ps);
+ }
+ } else {
+ /* Use already-committed state */
+ cstate = to_intel_crtc_state(crtc->state);
+ for_each_intel_plane_of_crtc(intel_crtc, intel_plane) {
+ if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) {
+ sprstate = to_intel_plane_state(intel_plane->base.state);
+ break;
+ }
}
+ pristate = to_intel_plane_state(crtc->primary->state);
+ curstate = to_intel_plane_state(crtc->cursor->state);
}
config.sprites_enabled = sprstate->visible;
@@ -2115,7 +2140,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16;
pipe_wm->pipe_enabled = cstate->base.active;
- pipe_wm->sprites_enabled = sprstate->visible;
+ pipe_wm->sprites_enabled = config.sprites_enabled;
pipe_wm->sprites_scaled = config.sprites_scaled;
/* ILK/SNB: LP2+ watermarks only w/o sprites */
@@ -2126,7 +2151,8 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
if (config.sprites_scaled)
max_level = 0;
- ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, &pipe_wm->wm[0]);
+ ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate,
+ pristate, sprstate, curstate, &pipe_wm->wm[0]);
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
@@ -2136,14 +2162,15 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
/* At least LP0 must be valid */
if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
- return false;
+ return -EINVAL;
ilk_compute_wm_reg_maximums(dev, 1, &max);
for (level = 1; level <= max_level; level++) {
struct intel_wm_level wm = {};
- ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, &wm);
+ ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate,
+ pristate, sprstate, curstate, &wm);
/*
* Disable any watermark level that exceeds the
@@ -2156,7 +2183,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
pipe_wm->wm[level] = wm;
}
- return true;
+ return 0;
}
/*
@@ -3479,10 +3506,9 @@ 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 = {};
- intel_compute_pipe_wm(cstate, &pipe_wm);
+ ilk_compute_pipe_wm(crtc, NULL, &pipe_wm);
if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
return;
--
1.8.5.1
More information about the Intel-gfx
mailing list