mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 05:16:47 +07:00
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: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Clint Taylor <Clinton.A.Taylor@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
f015c55188
commit
6eb1a68172
@ -1515,6 +1515,8 @@ struct vlv_wm_values {
|
||||
uint8_t sprite[2];
|
||||
uint8_t primary;
|
||||
} ddl[3];
|
||||
uint8_t level;
|
||||
bool cxsr;
|
||||
};
|
||||
|
||||
struct skl_ddb_entry {
|
||||
|
@ -15453,7 +15453,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
||||
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);
|
||||
else if (HAS_PCH_SPLIT(dev))
|
||||
ilk_wm_get_hw_state(dev);
|
||||
|
@ -583,6 +583,7 @@ struct intel_plane_wm_parameters {
|
||||
bool scaled;
|
||||
u64 tiling;
|
||||
unsigned int rotation;
|
||||
uint16_t fifo_size;
|
||||
};
|
||||
|
||||
struct intel_plane {
|
||||
@ -1368,6 +1369,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv,
|
||||
unsigned long submitted);
|
||||
void intel_queue_rps_boost_for_request(struct drm_device *dev,
|
||||
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 skl_wm_get_hw_state(struct drm_device *dev);
|
||||
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,
|
||||
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,
|
||||
struct vlv_wm_values *wm)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
Loading…
Reference in New Issue
Block a user