Commit 6eb1a681 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/i915: Read wm values from hardware at init on CHV

Read out the current watermark settings from the hardware at driver init
time. This will allow us to compare the newly calculated values against
the currrent ones and potentially avoid needless WM updates.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarClint Taylor <Clinton.A.Taylor@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent f015c551
...@@ -1515,6 +1515,8 @@ struct vlv_wm_values { ...@@ -1515,6 +1515,8 @@ struct vlv_wm_values {
uint8_t sprite[2]; uint8_t sprite[2];
uint8_t primary; uint8_t primary;
} ddl[3]; } ddl[3];
uint8_t level;
bool cxsr;
}; };
struct skl_ddb_entry { struct skl_ddb_entry {
......
...@@ -15453,7 +15453,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, ...@@ -15453,7 +15453,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
pll->on = false; pll->on = false;
} }
if (IS_GEN9(dev)) if (IS_CHERRYVIEW(dev))
vlv_wm_get_hw_state(dev);
else if (IS_GEN9(dev))
skl_wm_get_hw_state(dev); skl_wm_get_hw_state(dev);
else if (HAS_PCH_SPLIT(dev)) else if (HAS_PCH_SPLIT(dev))
ilk_wm_get_hw_state(dev); ilk_wm_get_hw_state(dev);
......
...@@ -583,6 +583,7 @@ struct intel_plane_wm_parameters { ...@@ -583,6 +583,7 @@ struct intel_plane_wm_parameters {
bool scaled; bool scaled;
u64 tiling; u64 tiling;
unsigned int rotation; unsigned int rotation;
uint16_t fifo_size;
}; };
struct intel_plane { struct intel_plane {
...@@ -1368,6 +1369,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv, ...@@ -1368,6 +1369,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv,
unsigned long submitted); unsigned long submitted);
void intel_queue_rps_boost_for_request(struct drm_device *dev, void intel_queue_rps_boost_for_request(struct drm_device *dev,
struct drm_i915_gem_request *req); struct drm_i915_gem_request *req);
void vlv_wm_get_hw_state(struct drm_device *dev);
void ilk_wm_get_hw_state(struct drm_device *dev); void ilk_wm_get_hw_state(struct drm_device *dev);
void skl_wm_get_hw_state(struct drm_device *dev); void skl_wm_get_hw_state(struct drm_device *dev);
void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
......
...@@ -1006,6 +1006,14 @@ static int vlv_compute_wm(struct intel_crtc *crtc, ...@@ -1006,6 +1006,14 @@ static int vlv_compute_wm(struct intel_crtc *crtc,
return fifo_size - clamp(DIV_ROUND_UP(256 * entries, 64), 0, fifo_size - 8); return fifo_size - clamp(DIV_ROUND_UP(256 * entries, 64), 0, fifo_size - 8);
} }
enum vlv_wm_level {
VLV_WM_LEVEL_PM2,
VLV_WM_LEVEL_PM5,
VLV_WM_LEVEL_DDR_DVFS,
CHV_WM_NUM_LEVELS,
VLV_WM_NUM_LEVELS = 1,
};
static bool vlv_compute_sr_wm(struct drm_device *dev, static bool vlv_compute_sr_wm(struct drm_device *dev,
struct vlv_wm_values *wm) struct vlv_wm_values *wm)
{ {
...@@ -3689,6 +3697,139 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) ...@@ -3689,6 +3697,139 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
} }
} }
#define _FW_WM(value, plane) \
(((value) & DSPFW_ ## plane ## _MASK) >> DSPFW_ ## plane ## _SHIFT)
#define _FW_WM_VLV(value, plane) \
(((value) & DSPFW_ ## plane ## _MASK_VLV) >> DSPFW_ ## plane ## _SHIFT)
static void vlv_read_wm_values(struct drm_i915_private *dev_priv,
struct vlv_wm_values *wm)
{
enum pipe pipe;
uint32_t tmp;
for_each_pipe(dev_priv, pipe) {
tmp = I915_READ(VLV_DDL(pipe));
wm->ddl[pipe].primary =
(tmp >> DDL_PLANE_SHIFT) & (DDL_PRECISION_HIGH | DRAIN_LATENCY_MASK);
wm->ddl[pipe].cursor =
(tmp >> DDL_CURSOR_SHIFT) & (DDL_PRECISION_HIGH | DRAIN_LATENCY_MASK);
wm->ddl[pipe].sprite[0] =
(tmp >> DDL_SPRITE_SHIFT(0)) & (DDL_PRECISION_HIGH | DRAIN_LATENCY_MASK);
wm->ddl[pipe].sprite[1] =
(tmp >> DDL_SPRITE_SHIFT(1)) & (DDL_PRECISION_HIGH | DRAIN_LATENCY_MASK);
}
tmp = I915_READ(DSPFW1);
wm->sr.plane = _FW_WM(tmp, SR);
wm->pipe[PIPE_B].cursor = _FW_WM(tmp, CURSORB);
wm->pipe[PIPE_B].primary = _FW_WM_VLV(tmp, PLANEB);
wm->pipe[PIPE_A].primary = _FW_WM_VLV(tmp, PLANEA);
tmp = I915_READ(DSPFW2);
wm->pipe[PIPE_A].sprite[1] = _FW_WM_VLV(tmp, SPRITEB);
wm->pipe[PIPE_A].cursor = _FW_WM(tmp, CURSORA);
wm->pipe[PIPE_A].sprite[0] = _FW_WM_VLV(tmp, SPRITEA);
tmp = I915_READ(DSPFW3);
wm->sr.cursor = _FW_WM(tmp, CURSOR_SR);
if (IS_CHERRYVIEW(dev_priv)) {
tmp = I915_READ(DSPFW7_CHV);
wm->pipe[PIPE_B].sprite[1] = _FW_WM_VLV(tmp, SPRITED);
wm->pipe[PIPE_B].sprite[0] = _FW_WM_VLV(tmp, SPRITEC);
tmp = I915_READ(DSPFW8_CHV);
wm->pipe[PIPE_C].sprite[1] = _FW_WM_VLV(tmp, SPRITEF);
wm->pipe[PIPE_C].sprite[0] = _FW_WM_VLV(tmp, SPRITEE);
tmp = I915_READ(DSPFW9_CHV);
wm->pipe[PIPE_C].primary = _FW_WM_VLV(tmp, PLANEC);
wm->pipe[PIPE_C].cursor = _FW_WM(tmp, CURSORC);
tmp = I915_READ(DSPHOWM);
wm->sr.plane |= _FW_WM(tmp, SR_HI) << 9;
wm->pipe[PIPE_C].sprite[1] |= _FW_WM(tmp, SPRITEF_HI) << 8;
wm->pipe[PIPE_C].sprite[0] |= _FW_WM(tmp, SPRITEE_HI) << 8;
wm->pipe[PIPE_C].primary |= _FW_WM(tmp, PLANEC_HI) << 8;
wm->pipe[PIPE_B].sprite[1] |= _FW_WM(tmp, SPRITED_HI) << 8;
wm->pipe[PIPE_B].sprite[0] |= _FW_WM(tmp, SPRITEC_HI) << 8;
wm->pipe[PIPE_B].primary |= _FW_WM(tmp, PLANEB_HI) << 8;
wm->pipe[PIPE_A].sprite[1] |= _FW_WM(tmp, SPRITEB_HI) << 8;
wm->pipe[PIPE_A].sprite[0] |= _FW_WM(tmp, SPRITEA_HI) << 8;
wm->pipe[PIPE_A].primary |= _FW_WM(tmp, PLANEA_HI) << 8;
} else {
tmp = I915_READ(DSPFW7);
wm->pipe[PIPE_B].sprite[1] = _FW_WM_VLV(tmp, SPRITED);
wm->pipe[PIPE_B].sprite[0] = _FW_WM_VLV(tmp, SPRITEC);
tmp = I915_READ(DSPHOWM);
wm->sr.plane |= _FW_WM(tmp, SR_HI) << 9;
wm->pipe[PIPE_B].sprite[1] |= _FW_WM(tmp, SPRITED_HI) << 8;
wm->pipe[PIPE_B].sprite[0] |= _FW_WM(tmp, SPRITEC_HI) << 8;
wm->pipe[PIPE_B].primary |= _FW_WM(tmp, PLANEB_HI) << 8;
wm->pipe[PIPE_A].sprite[1] |= _FW_WM(tmp, SPRITEB_HI) << 8;
wm->pipe[PIPE_A].sprite[0] |= _FW_WM(tmp, SPRITEA_HI) << 8;
wm->pipe[PIPE_A].primary |= _FW_WM(tmp, PLANEA_HI) << 8;
}
}
#undef _FW_WM
#undef _FW_WM_VLV
void vlv_wm_get_hw_state(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct vlv_wm_values *wm = &dev_priv->wm.vlv;
struct intel_plane *plane;
enum pipe pipe;
u32 val;
vlv_read_wm_values(dev_priv, wm);
for_each_intel_plane(dev, plane) {
switch (plane->base.type) {
int sprite;
case DRM_PLANE_TYPE_CURSOR:
plane->wm.fifo_size = 63;
break;
case DRM_PLANE_TYPE_PRIMARY:
plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, 0);
break;
case DRM_PLANE_TYPE_OVERLAY:
sprite = plane->plane;
plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, sprite + 1);
break;
}
}
wm->cxsr = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
wm->level = VLV_WM_LEVEL_PM2;
if (IS_CHERRYVIEW(dev_priv)) {
mutex_lock(&dev_priv->rps.hw_lock);
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
if (val & DSP_MAXFIFO_PM5_ENABLE)
wm->level = VLV_WM_LEVEL_PM5;
val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2);
if ((val & FORCE_DDR_HIGH_FREQ) == 0)
wm->level = VLV_WM_LEVEL_DDR_DVFS;
mutex_unlock(&dev_priv->rps.hw_lock);
}
for_each_pipe(dev_priv, pipe)
DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n",
pipe_name(pipe), wm->pipe[pipe].primary, wm->pipe[pipe].cursor,
wm->pipe[pipe].sprite[0], wm->pipe[pipe].sprite[1]);
DRM_DEBUG_KMS("Initial watermarks: SR plane=%d, SR cursor=%d level=%d cxsr=%d\n",
wm->sr.plane, wm->sr.cursor, wm->level, wm->cxsr);
}
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 = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment