drm/i915: Calculate pipe watermarks into CRTC state (v3)

A future patch will calculate these during the atomic 'check' phase
rather than at WM programming time, so let's store the watermark
values we're planning to use in the CRTC state; the values actually
active on the hardware remains in intel_crtc.

While we're at it, do some minor restructuring to keep ILK and SKL
values in a union.

v2: Don't move cxsr_allowed to state (Maarten)

v3: Only calculate watermarks in state.  Still keep active watermarks in
    intel_crtc itself.  (Ville)

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:15 -07:00 committed by Daniel Vetter
parent de165e0bcc
commit de4a9f8339
2 changed files with 57 additions and 35 deletions

View File

@ -332,6 +332,21 @@ struct intel_crtc_scaler_state {
/* drm_mode->private_flags */ /* drm_mode->private_flags */
#define I915_MODE_FLAG_INHERITED 1 #define I915_MODE_FLAG_INHERITED 1
struct intel_pipe_wm {
struct intel_wm_level wm[5];
uint32_t linetime;
bool fbc_wm_enabled;
bool pipe_enabled;
bool sprites_enabled;
bool sprites_scaled;
};
struct skl_pipe_wm {
struct skl_wm_level wm[8];
struct skl_wm_level trans_wm;
uint32_t linetime;
};
struct intel_crtc_state { struct intel_crtc_state {
struct drm_crtc_state base; struct drm_crtc_state base;
@ -469,6 +484,17 @@ struct intel_crtc_state {
/* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */ /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
bool disable_lp_wm; bool disable_lp_wm;
struct {
/*
* optimal watermarks, programmed post-vblank when this state
* is committed
*/
union {
struct intel_pipe_wm ilk;
struct skl_pipe_wm skl;
} optimal;
} wm;
}; };
struct vlv_wm_state { struct vlv_wm_state {
@ -480,15 +506,6 @@ struct vlv_wm_state {
bool cxsr; bool cxsr;
}; };
struct intel_pipe_wm {
struct intel_wm_level wm[5];
uint32_t linetime;
bool fbc_wm_enabled;
bool pipe_enabled;
bool sprites_enabled;
bool sprites_scaled;
};
struct intel_mmio_flip { struct intel_mmio_flip {
struct work_struct work; struct work_struct work;
struct drm_i915_private *i915; struct drm_i915_private *i915;
@ -496,12 +513,6 @@ struct intel_mmio_flip {
struct intel_crtc *crtc; struct intel_crtc *crtc;
}; };
struct skl_pipe_wm {
struct skl_wm_level wm[8];
struct skl_wm_level trans_wm;
uint32_t linetime;
};
/* /*
* Tracking of operations that need to be performed at the beginning/end of an * Tracking of operations that need to be performed at the beginning/end of an
* atomic commit, outside the atomic section where interrupts are disabled. * atomic commit, outside the atomic section where interrupts are disabled.
@ -569,9 +580,10 @@ struct intel_crtc {
/* per-pipe watermark state */ /* per-pipe watermark state */
struct { struct {
/* watermarks currently being used */ /* watermarks currently being used */
struct intel_pipe_wm active; union {
/* SKL wm values currently in use */ struct intel_pipe_wm ilk;
struct skl_pipe_wm skl_active; struct skl_pipe_wm skl;
} active;
/* allow CxSR on this pipe */ /* allow CxSR on this pipe */
bool cxsr_allowed; bool cxsr_allowed;
} wm; } wm;

View File

@ -2331,7 +2331,7 @@ static void ilk_compute_wm_config(struct drm_device *dev,
/* Compute the currently _active_ config */ /* Compute the currently _active_ config */
for_each_intel_crtc(dev, intel_crtc) { for_each_intel_crtc(dev, intel_crtc) {
const struct intel_pipe_wm *wm = &intel_crtc->wm.active; const struct intel_pipe_wm *wm = &intel_crtc->wm.active.ilk;
if (!wm->pipe_enabled) if (!wm->pipe_enabled)
continue; continue;
@ -2428,7 +2428,9 @@ static void ilk_merge_wm_level(struct drm_device *dev,
ret_wm->enable = true; ret_wm->enable = true;
for_each_intel_crtc(dev, intel_crtc) { for_each_intel_crtc(dev, intel_crtc) {
const struct intel_pipe_wm *active = &intel_crtc->wm.active; const struct intel_crtc_state *cstate =
to_intel_crtc_state(intel_crtc->base.state);
const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
const struct intel_wm_level *wm = &active->wm[level]; const struct intel_wm_level *wm = &active->wm[level];
if (!active->pipe_enabled) if (!active->pipe_enabled)
@ -2576,14 +2578,15 @@ static void ilk_compute_wm_results(struct drm_device *dev,
/* LP0 register values */ /* LP0 register values */
for_each_intel_crtc(dev, intel_crtc) { for_each_intel_crtc(dev, intel_crtc) {
const struct intel_crtc_state *cstate =
to_intel_crtc_state(intel_crtc->base.state);
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
const struct intel_wm_level *r = const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];
&intel_crtc->wm.active.wm[0];
if (WARN_ON(!r->enable)) if (WARN_ON(!r->enable))
continue; continue;
results->wm_linetime[pipe] = intel_crtc->wm.active.linetime; results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;
results->wm_pipe[pipe] = results->wm_pipe[pipe] =
(r->pri_val << WM0_PIPE_PLANE_SHIFT) | (r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@ -3567,10 +3570,10 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
skl_allocate_pipe_ddb(cstate, config, ddb); skl_allocate_pipe_ddb(cstate, config, ddb);
skl_compute_pipe_wm(cstate, ddb, pipe_wm); skl_compute_pipe_wm(cstate, ddb, pipe_wm);
if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm))) if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
return false; return false;
intel_crtc->wm.skl_active = *pipe_wm; intel_crtc->wm.active.skl = *pipe_wm;
return true; return true;
} }
@ -3648,7 +3651,8 @@ static void skl_update_wm(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct skl_wm_values *results = &dev_priv->wm.skl_results; struct skl_wm_values *results = &dev_priv->wm.skl_results;
struct skl_pipe_wm pipe_wm = {}; struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
struct skl_pipe_wm *pipe_wm = &cstate->wm.optimal.skl;
struct intel_wm_config config = {}; struct intel_wm_config config = {};
@ -3659,10 +3663,10 @@ static void skl_update_wm(struct drm_crtc *crtc)
skl_compute_wm_global_parameters(dev, &config); skl_compute_wm_global_parameters(dev, &config);
if (!skl_update_pipe_wm(crtc, &config, &results->ddb, &pipe_wm)) if (!skl_update_pipe_wm(crtc, &config, &results->ddb, pipe_wm))
return; return;
skl_compute_wm_results(dev, &pipe_wm, results, intel_crtc); skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
results->dirty[intel_crtc->pipe] = true; results->dirty[intel_crtc->pipe] = true;
skl_update_other_pipe_wm(dev, crtc, &config, results); skl_update_other_pipe_wm(dev, crtc, &config, results);
@ -3711,7 +3715,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
struct intel_pipe_wm pipe_wm = {};
WARN_ON(cstate->base.active != intel_crtc->active); WARN_ON(cstate->base.active != intel_crtc->active);
@ -3727,12 +3730,13 @@ static void ilk_update_wm(struct drm_crtc *crtc)
intel_wait_for_vblank(crtc->dev, intel_crtc->pipe); intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
} }
intel_compute_pipe_wm(cstate, &pipe_wm); intel_compute_pipe_wm(cstate, &cstate->wm.optimal.ilk);
if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm))) if (!memcmp(&intel_crtc->wm.active.ilk,
return; &cstate->wm.optimal.ilk,
sizeof(cstate->wm.optimal.ilk)));
intel_crtc->wm.active = pipe_wm; intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
ilk_program_watermarks(dev_priv); ilk_program_watermarks(dev_priv);
} }
@ -3787,7 +3791,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct skl_wm_values *hw = &dev_priv->wm.skl_hw; struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct skl_pipe_wm *active = &intel_crtc->wm.skl_active; struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
struct skl_pipe_wm *active = &cstate->wm.optimal.skl;
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
int level, i, max_level; int level, i, max_level;
uint32_t temp; uint32_t temp;
@ -3831,6 +3836,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
temp = hw->plane_trans[pipe][PLANE_CURSOR]; temp = hw->plane_trans[pipe][PLANE_CURSOR];
skl_pipe_wm_active_state(temp, active, true, true, i, 0); skl_pipe_wm_active_state(temp, active, true, true, i, 0);
intel_crtc->wm.active.skl = *active;
} }
void skl_wm_get_hw_state(struct drm_device *dev) void skl_wm_get_hw_state(struct drm_device *dev)
@ -3850,7 +3857,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct ilk_wm_values *hw = &dev_priv->wm.hw; struct ilk_wm_values *hw = &dev_priv->wm.hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_pipe_wm *active = &intel_crtc->wm.active; struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
static const unsigned int wm0_pipe_reg[] = { static const unsigned int wm0_pipe_reg[] = {
[PIPE_A] = WM0_PIPEA_ILK, [PIPE_A] = WM0_PIPEA_ILK,
@ -3889,6 +3897,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
for (level = 0; level <= max_level; level++) for (level = 0; level <= max_level; level++)
active->wm[level].enable = true; active->wm[level].enable = true;
} }
intel_crtc->wm.active.ilk = *active;
} }
#define _FW_WM(value, plane) \ #define _FW_WM(value, plane) \