Commit 243e6a44 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()

Fill out the HSW watermark s/w tracking structures with the current
hardware state in intel_modeset_setup_hw_state(). This allows us to skip
the HW state readback during watermark programming and just use the values
we keep around in dev_priv->wm. Reduces the overhead of the watermark
programming quite a bit.

v2: s/init_wm/wm_get_hw_state
    Remove stale comment about sprites
    Make DDB partitioning readout safer
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
[danvet: Fix whitespace fail.]
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 49a687c4
...@@ -10839,6 +10839,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, ...@@ -10839,6 +10839,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
pll->on = false; pll->on = false;
} }
if (IS_HASWELL(dev))
ilk_wm_get_hw_state(dev);
if (force_restore) { if (force_restore) {
i915_redisable_vga(dev); i915_redisable_vga(dev);
......
...@@ -839,6 +839,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv); ...@@ -839,6 +839,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
void gen6_rps_boost(struct drm_i915_private *dev_priv); void gen6_rps_boost(struct drm_i915_private *dev_priv);
void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
void ilk_wm_get_hw_state(struct drm_device *dev);
/* intel_sdvo.c */ /* intel_sdvo.c */
......
...@@ -2843,37 +2843,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, ...@@ -2843,37 +2843,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
static void hsw_write_wm_values(struct drm_i915_private *dev_priv, static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
struct hsw_wm_values *results) struct hsw_wm_values *results)
{ {
struct hsw_wm_values previous; struct hsw_wm_values *previous = &dev_priv->wm.hw;
unsigned int dirty; unsigned int dirty;
uint32_t val; uint32_t val;
previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK); dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
if (!dirty) if (!dirty)
return; return;
if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0) if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
I915_WRITE(WM3_LP_ILK, 0); I915_WRITE(WM3_LP_ILK, 0);
if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0) if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0);
if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0) if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
I915_WRITE(WM1_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0);
if (dirty & WM_DIRTY_PIPE(PIPE_A)) if (dirty & WM_DIRTY_PIPE(PIPE_A))
...@@ -2908,11 +2890,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, ...@@ -2908,11 +2890,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
I915_WRITE(DISP_ARB_CTL, val); I915_WRITE(DISP_ARB_CTL, val);
} }
if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0]) if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1]) if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]); I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2]) if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0) if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
...@@ -3145,6 +3127,74 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane, ...@@ -3145,6 +3127,74 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
I915_WRITE(WM3S_LP_IVB, sprite_wm); I915_WRITE(WM3S_LP_IVB, sprite_wm);
} }
static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct hsw_wm_values *hw = &dev_priv->wm.hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_pipe_wm *active = &intel_crtc->wm.active;
enum pipe pipe = intel_crtc->pipe;
static const unsigned int wm0_pipe_reg[] = {
[PIPE_A] = WM0_PIPEA_ILK,
[PIPE_B] = WM0_PIPEB_ILK,
[PIPE_C] = WM0_PIPEC_IVB,
};
hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
if (intel_crtc_active(crtc)) {
u32 tmp = hw->wm_pipe[pipe];
/*
* For active pipes LP0 watermark is marked as
* enabled, and LP1+ watermaks as disabled since
* we can't really reverse compute them in case
* multiple pipes are active.
*/
active->wm[0].enable = true;
active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
active->linetime = hw->wm_linetime[pipe];
} else {
int level, max_level = ilk_wm_max_level(dev);
/*
* For inactive pipes, all watermark levels
* should be marked as enabled but zeroed,
* which is what we'd compute them to.
*/
for (level = 0; level <= max_level; level++)
active->wm[level].enable = true;
}
}
void ilk_wm_get_hw_state(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct hsw_wm_values *hw = &dev_priv->wm.hw;
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
ilk_pipe_wm_get_hw_state(crtc);
hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
hw->enable_fbc_wm =
!(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
}
/** /**
* intel_update_watermarks - update FIFO watermark values based on current modes * intel_update_watermarks - update FIFO watermark values based on current modes
* *
......
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