drm/i915: Two stage watermarks for g4x
Implement proper two stage watermark programming for g4x. As with other pre-SKL platforms, the watermark registers aren't double buffered on g4x. Hence we must sequence the watermark update carefully around plane updates. The code is quite heavily modelled on the VLV/CHV code, with some fairly significant differences due to the different hardware architecture: * g4x doesn't use inverted watermark values * CxSR actually affects the watermarks since it controls memory self refresh in addition to the max FIFO mode * A further HPLL SR mode is possible with higher memory wakeup latency * g4x has FBC2 and so it also has FBC watermarks * max FIFO mode for primary plane only (cursor is allowed, sprite is not) * g4x has no manual FIFO repartitioning * some TLB miss related workarounds are needed for the watermarks Actually the hardware is quite similar to ILK+ in many ways. The most visible differences are in the actual watermakr register layout. ILK revamped that part quite heavily whereas g4x is still using the layout inherited from earlier platforms. Note that we didn't previously enable the HPLL SR on g4x. So in order to not introduce too many functional changes in this patch I've not actually enabled it here either, even though the code is now fully ready for it. We'll enable it separately later on. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170421181432.15216-13-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
This commit is contained in:
parent
42f4ac66c5
commit
04548cbada
@ -3892,6 +3892,8 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
|
||||
num_levels = 3;
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
num_levels = 1;
|
||||
else if (IS_G4X(dev_priv))
|
||||
num_levels = 3;
|
||||
else
|
||||
num_levels = ilk_wm_max_level(dev_priv) + 1;
|
||||
|
||||
@ -3904,8 +3906,10 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
|
||||
* - WM1+ latency values in 0.5us units
|
||||
* - latencies are in us on gen9/vlv/chv
|
||||
*/
|
||||
if (INTEL_GEN(dev_priv) >= 9 || IS_VALLEYVIEW(dev_priv) ||
|
||||
IS_CHERRYVIEW(dev_priv))
|
||||
if (INTEL_GEN(dev_priv) >= 9 ||
|
||||
IS_VALLEYVIEW(dev_priv) ||
|
||||
IS_CHERRYVIEW(dev_priv) ||
|
||||
IS_G4X(dev_priv))
|
||||
latency *= 10;
|
||||
else if (level > 0)
|
||||
latency *= 5;
|
||||
@ -3966,7 +3970,7 @@ static int pri_wm_latency_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = inode->i_private;
|
||||
|
||||
if (INTEL_GEN(dev_priv) < 5)
|
||||
if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
|
||||
return -ENODEV;
|
||||
|
||||
return single_open(file, pri_wm_latency_show, dev_priv);
|
||||
@ -4008,6 +4012,8 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
num_levels = 3;
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
num_levels = 1;
|
||||
else if (IS_G4X(dev_priv))
|
||||
num_levels = 3;
|
||||
else
|
||||
num_levels = ilk_wm_max_level(dev_priv) + 1;
|
||||
|
||||
|
@ -1654,11 +1654,13 @@ struct ilk_wm_values {
|
||||
|
||||
struct g4x_pipe_wm {
|
||||
uint16_t plane[I915_MAX_PLANES];
|
||||
uint16_t fbc;
|
||||
};
|
||||
|
||||
struct g4x_sr_wm {
|
||||
uint16_t plane;
|
||||
uint16_t cursor;
|
||||
uint16_t fbc;
|
||||
};
|
||||
|
||||
struct vlv_wm_ddl_values {
|
||||
@ -1673,6 +1675,15 @@ struct vlv_wm_values {
|
||||
bool cxsr;
|
||||
};
|
||||
|
||||
struct g4x_wm_values {
|
||||
struct g4x_pipe_wm pipe[2];
|
||||
struct g4x_sr_wm sr;
|
||||
struct g4x_sr_wm hpll;
|
||||
bool cxsr;
|
||||
bool hpll_en;
|
||||
bool fbc_en;
|
||||
};
|
||||
|
||||
struct skl_ddb_entry {
|
||||
uint16_t start, end; /* in number of blocks, 'end' is exclusive */
|
||||
};
|
||||
@ -2301,6 +2312,7 @@ struct drm_i915_private {
|
||||
struct ilk_wm_values hw;
|
||||
struct skl_wm_values skl_hw;
|
||||
struct vlv_wm_values vlv;
|
||||
struct g4x_wm_values g4x;
|
||||
};
|
||||
|
||||
uint8_t max_level;
|
||||
|
@ -5719,6 +5719,8 @@ static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
|
||||
static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
|
||||
struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct intel_atomic_state *old_intel_state =
|
||||
to_intel_atomic_state(old_state);
|
||||
struct drm_crtc *crtc = pipe_config->base.crtc;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
@ -5751,7 +5753,11 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
|
||||
|
||||
intel_color_load_luts(&pipe_config->base);
|
||||
|
||||
intel_update_watermarks(intel_crtc);
|
||||
if (dev_priv->display.initial_watermarks != NULL)
|
||||
dev_priv->display.initial_watermarks(old_intel_state,
|
||||
intel_crtc->config);
|
||||
else
|
||||
intel_update_watermarks(intel_crtc);
|
||||
intel_enable_pipe(intel_crtc);
|
||||
|
||||
assert_vblank_disabled(crtc);
|
||||
@ -10852,21 +10858,21 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
||||
turn_off, turn_on, mode_changed);
|
||||
|
||||
if (turn_on) {
|
||||
if (INTEL_GEN(dev_priv) < 5)
|
||||
if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
|
||||
pipe_config->update_wm_pre = true;
|
||||
|
||||
/* must disable cxsr around plane enable/disable */
|
||||
if (plane->id != PLANE_CURSOR)
|
||||
pipe_config->disable_cxsr = true;
|
||||
} else if (turn_off) {
|
||||
if (INTEL_GEN(dev_priv) < 5)
|
||||
if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
|
||||
pipe_config->update_wm_post = true;
|
||||
|
||||
/* must disable cxsr around plane enable/disable */
|
||||
if (plane->id != PLANE_CURSOR)
|
||||
pipe_config->disable_cxsr = true;
|
||||
} else if (intel_wm_need_update(&plane->base, plane_state)) {
|
||||
if (INTEL_GEN(dev_priv) < 5) {
|
||||
if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) {
|
||||
/* FIXME bollocks */
|
||||
pipe_config->update_wm_pre = true;
|
||||
pipe_config->update_wm_post = true;
|
||||
@ -11290,7 +11296,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
|
||||
shared_dpll = crtc_state->shared_dpll;
|
||||
dpll_hw_state = crtc_state->dpll_hw_state;
|
||||
force_thru = crtc_state->pch_pfit.force_thru;
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
if (IS_G4X(dev_priv) ||
|
||||
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
wm_state = crtc_state->wm;
|
||||
|
||||
/* Keep base drm_crtc_state intact, only clear our extended struct */
|
||||
@ -11302,7 +11309,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
|
||||
crtc_state->shared_dpll = shared_dpll;
|
||||
crtc_state->dpll_hw_state = dpll_hw_state;
|
||||
crtc_state->pch_pfit.force_thru = force_thru;
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
if (IS_G4X(dev_priv) ||
|
||||
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
crtc_state->wm = wm_state;
|
||||
}
|
||||
|
||||
@ -15527,7 +15535,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
|
||||
pll->on = false;
|
||||
}
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
if (IS_G4X(dev_priv)) {
|
||||
g4x_wm_get_hw_state(dev);
|
||||
g4x_wm_sanitize(dev_priv);
|
||||
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
vlv_wm_get_hw_state(dev);
|
||||
vlv_wm_sanitize(dev_priv);
|
||||
} else if (IS_GEN9(dev_priv)) {
|
||||
|
@ -522,6 +522,22 @@ struct vlv_fifo_state {
|
||||
u16 plane[I915_MAX_PLANES];
|
||||
};
|
||||
|
||||
enum g4x_wm_level {
|
||||
G4X_WM_LEVEL_NORMAL,
|
||||
G4X_WM_LEVEL_SR,
|
||||
G4X_WM_LEVEL_HPLL,
|
||||
NUM_G4X_WM_LEVELS,
|
||||
};
|
||||
|
||||
struct g4x_wm_state {
|
||||
struct g4x_pipe_wm wm;
|
||||
struct g4x_sr_wm sr;
|
||||
struct g4x_sr_wm hpll;
|
||||
bool cxsr;
|
||||
bool hpll_en;
|
||||
bool fbc_en;
|
||||
};
|
||||
|
||||
struct intel_crtc_wm_state {
|
||||
union {
|
||||
struct {
|
||||
@ -557,6 +573,15 @@ struct intel_crtc_wm_state {
|
||||
/* display FIFO split */
|
||||
struct vlv_fifo_state fifo_state;
|
||||
} vlv;
|
||||
|
||||
struct {
|
||||
/* "raw" watermarks */
|
||||
struct g4x_pipe_wm raw[NUM_G4X_WM_LEVELS];
|
||||
/* intermediate watermarks */
|
||||
struct g4x_wm_state intermediate;
|
||||
/* optimal watermarks */
|
||||
struct g4x_wm_state optimal;
|
||||
} g4x;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -794,6 +819,7 @@ struct intel_crtc {
|
||||
union {
|
||||
struct intel_pipe_wm ilk;
|
||||
struct vlv_wm_state vlv;
|
||||
struct g4x_wm_state g4x;
|
||||
} active;
|
||||
} wm;
|
||||
|
||||
@ -1841,6 +1867,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv,
|
||||
struct intel_rps_client *rps,
|
||||
unsigned long submitted);
|
||||
void intel_queue_rps_boost_for_request(struct drm_i915_gem_request *req);
|
||||
void g4x_wm_get_hw_state(struct drm_device *dev);
|
||||
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);
|
||||
@ -1848,6 +1875,7 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct skl_ddb_allocation *ddb /* out */);
|
||||
void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
|
||||
struct skl_pipe_wm *out);
|
||||
void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
|
||||
void vlv_wm_sanitize(struct drm_i915_private *dev_priv);
|
||||
bool intel_can_enable_sagv(struct drm_atomic_state *state);
|
||||
int intel_enable_sagv(struct drm_i915_private *dev_priv);
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user