This patch implemnets Workariunds related to display arbitrated
memory
bandwidth. These WA are applicabe for all gen-9 based platforms.
Changes since v1:
- Rebase on top of Paulo's patch series
Changes since v2:
- Address review comments
- Rebase/rework as per other patch changes in series
Signed-off-by: Mahesh Kumar <mahesh1.kumar@xxxxxxxxx>
---
drivers/gpu/drm/i915/i915_drv.h | 9 +++
drivers/gpu/drm/i915/intel_pm.c | 149
+++++++++++++++++++++++++++++++++++++---
2 files changed, 149 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h
b/drivers/gpu/drm/i915/i915_drv.h
index 4e2f17f..2b673c6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1193,6 +1193,13 @@ enum intel_sbi_destination {
SBI_MPHY,
};
+/* SKL+ Watermark arbitrated display bandwidth Workarounds */
+enum watermark_memory_wa {
+ WATERMARK_WA_NONE,
+ WATERMARK_WA_X_TILED,
+ WATERMARK_WA_Y_TILED,
+};
+
#define QUIRK_PIPEA_FORCE (1<<0)
#define QUIRK_LVDS_SSC_DISABLE (1<<1)
#define QUIRK_INVERT_BRIGHTNESS (1<<2)
@@ -1764,6 +1771,8 @@ struct skl_ddb_allocation {
struct skl_wm_values {
unsigned dirty_pipes;
+ /* any WaterMark memory workaround Required */
+ enum watermark_memory_wa mem_wa;
struct skl_ddb_allocation ddb;
};
diff --git a/drivers/gpu/drm/i915/intel_pm.c
b/drivers/gpu/drm/i915/intel_pm.c
index 3e2dd8f..547bbda 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2889,11 +2889,7 @@ skl_wm_plane_id(const struct intel_plane
*plane)
}
}
-/*
- * FIXME: We still don't have the proper code detect if we need
to
apply the WA,
- * so assume we'll always need it in order to avoid underruns.
- */
-static bool skl_needs_memory_bw_wa(struct intel_atomic_state
*state)
+static bool intel_needs_memory_bw_wa(struct intel_atomic_state
*state)
{
struct drm_i915_private *dev_priv = to_i915(state-
base.dev);
@@ -3067,7 +3063,7 @@ bool intel_can_enable_sagv(struct
drm_atomic_state *state)
latency = dev_priv->wm.skl_latency[level];
- if (skl_needs_memory_bw_wa(intel_state) &&
+ if (intel_needs_memory_bw_wa(intel_state) &&
plane->base.state->fb->modifier ==
I915_FORMAT_MOD_X_TILED)
latency += 15;
@@ -3597,7 +3593,7 @@ static int skl_compute_plane_wm(const
struct
drm_i915_private *dev_priv,
uint32_t y_min_scanlines;
struct intel_atomic_state *state =
to_intel_atomic_state(cstate->base.state);
- bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state);
+ enum watermark_memory_wa mem_wa;
bool y_tiled, x_tiled;
if (latency == 0 || !cstate->base.active ||
!intel_pstate-
base.visible) {
@@ -3613,7 +3609,8 @@ static int skl_compute_plane_wm(const
struct
drm_i915_private *dev_priv,
if (IS_KABYLAKE(dev_priv) && dev_priv->ipc_enabled)
latency += 4;
- if (apply_memory_bw_wa && x_tiled)
+ mem_wa = state->wm_results.mem_wa;
+ if (mem_wa != WATERMARK_WA_NONE && x_tiled)
latency += 15;
width = drm_rect_width(&intel_pstate->base.src) >> 16;
@@ -3648,7 +3645,7 @@ static int skl_compute_plane_wm(const
struct
drm_i915_private *dev_priv,
y_min_scanlines = 4;
}
- if (apply_memory_bw_wa)
+ if (mem_wa == WATERMARK_WA_Y_TILED)
y_min_scanlines *= 2;
plane_bytes_per_line = width * cpp;
@@ -4077,6 +4074,15 @@ skl_compute_ddb(struct drm_atomic_state
*state)
}
/*
+ * If Watermark workaround is changed we need to
recalculate
+ * watermark values for all active pipes
+ */
+ if (intel_state->wm_results.mem_wa != dev_priv-
wm.skl_hw.mem_wa) {
+ realloc_pipes = ~0;
+ intel_state->wm_results.dirty_pipes = ~0;
+ }
+
+ /*
* We're not recomputing for the pipes not included in
the
commit, so
* make sure we start with the current state.
*/
@@ -4102,6 +4108,129 @@ skl_compute_ddb(struct drm_atomic_state
*state)
}
static void
+skl_compute_memory_bandwidth_wm_wa(struct drm_atomic_state
*state)
+{
+ struct drm_device *dev = state->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_crtc *intel_crtc;
+ struct intel_plane_state *intel_pstate;
+ struct intel_atomic_state *intel_state =
to_intel_atomic_state(state);
+ struct memdev_info *memdev_info = &dev_priv-
memdev_info;
+ int num_active_pipes;
+ uint32_t max_pipe_bw_kbps, total_pipe_bw_kbps;
+ int display_bw_percentage;
+ bool y_tile_enabled = false;
+
+ if (!intel_needs_memory_bw_wa(intel_state)) {
+ intel_state->wm_results.mem_wa =
WATERMARK_WA_NONE;
+ return;
+ }
+
+ if (!memdev_info->valid)
+ goto exit;
+
+ max_pipe_bw_kbps = 0;
+ num_active_pipes = 0;
+ for_each_intel_crtc(dev, intel_crtc) {
+ struct intel_crtc_state *cstate;
+ struct intel_plane *plane;
+ int num_active_planes;
+ uint32_t max_plane_bw_kbps, pipe_bw_kbps;
+
+ /*
+ * If CRTC is part of current atomic commit, get
crtc state from
+ * existing CRTC state. else take the cached
CRTC
state
+ */
+ cstate = NULL;
+ if (state)
+ cstate =
intel_atomic_get_existing_crtc_state(state,
+ intel_crtc);
+ if (!cstate)
+ cstate = to_intel_crtc_state(intel_crtc-
base.state);