diff options
Diffstat (limited to '0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch')
-rw-r--r-- | 0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch b/0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch new file mode 100644 index 000000000..134ffad16 --- /dev/null +++ b/0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch @@ -0,0 +1,244 @@ +From 0830cf3698b5966d3409745f751fb6d3a555c254 Mon Sep 17 00:00:00 2001 +From: Matt Roper <matthew.d.roper@intel.com> +Date: Thu, 12 May 2016 07:06:08 -0700 +Subject: [PATCH 14/17] drm/i915/gen9: Propagate watermark calculation failures + up the call chain + +Once we move watermark calculation to the atomic check phase, we'll want +to start rejecting display configurations that exceed out watermark +limits. At the moment we just assume that there's always a valid set of +watermarks, even though this may not actually be true. Let's prepare by +passing return codes up through the call stack in preparation. + +Signed-off-by: Matt Roper <matthew.d.roper@intel.com> +Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> +Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-15-git-send-email-matthew.d.roper@intel.com +--- + drivers/gpu/drm/i915/intel_display.c | 10 ++-- + drivers/gpu/drm/i915/intel_pm.c | 90 ++++++++++++++++++++++-------------- + 2 files changed, 61 insertions(+), 39 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 4db10d7..2190bac 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -13339,7 +13339,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) + * phase. The code here should be run after the per-crtc and per-plane 'check' + * handlers to ensure that all derived state has been updated. + */ +-static void calc_watermark_data(struct drm_atomic_state *state) ++static int calc_watermark_data(struct drm_atomic_state *state) + { + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); +@@ -13375,7 +13375,9 @@ static void calc_watermark_data(struct drm_atomic_state *state) + + /* Is there platform-specific watermark information to calculate? */ + if (dev_priv->display.compute_global_watermarks) +- dev_priv->display.compute_global_watermarks(state); ++ return dev_priv->display.compute_global_watermarks(state); ++ ++ return 0; + } + + /** +@@ -13459,9 +13461,7 @@ static int intel_atomic_check(struct drm_device *dev, + return ret; + + intel_fbc_choose_crtc(dev_priv, state); +- calc_watermark_data(state); +- +- return 0; ++ return calc_watermark_data(state); + } + + static int intel_atomic_prepare_commit(struct drm_device *dev, +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index cb6b6f4..342aa66 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3238,13 +3238,14 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb, + return false; + } + +-static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, +- struct intel_crtc_state *cstate, +- struct intel_plane_state *intel_pstate, +- uint16_t ddb_allocation, +- int level, +- uint16_t *out_blocks, /* out */ +- uint8_t *out_lines /* out */) ++static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, ++ struct intel_crtc_state *cstate, ++ struct intel_plane_state *intel_pstate, ++ uint16_t ddb_allocation, ++ int level, ++ uint16_t *out_blocks, /* out */ ++ uint8_t *out_lines, /* out */ ++ bool *enabled /* out */) + { + struct drm_plane_state *pstate = &intel_pstate->base; + struct drm_framebuffer *fb = pstate->fb; +@@ -3256,8 +3257,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + uint8_t cpp; + uint32_t width = 0, height = 0; + +- if (latency == 0 || !cstate->base.active || !intel_pstate->visible) +- return false; ++ if (latency == 0 || !cstate->base.active || !intel_pstate->visible) { ++ *enabled = false; ++ return 0; ++ } + + width = drm_rect_width(&intel_pstate->src) >> 16; + height = drm_rect_height(&intel_pstate->src) >> 16; +@@ -3318,13 +3321,16 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + res_blocks++; + } + +- if (res_blocks >= ddb_allocation || res_lines > 31) +- return false; ++ if (res_blocks >= ddb_allocation || res_lines > 31) { ++ *enabled = false; ++ return 0; ++ } + + *out_blocks = res_blocks; + *out_lines = res_lines; ++ *enabled = true; + +- return true; ++ return 0; + } + + static int +@@ -3342,6 +3348,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, + struct intel_plane_state *intel_pstate; + uint16_t ddb_blocks; + enum pipe pipe = intel_crtc->pipe; ++ int ret; + + /* + * We'll only calculate watermarks for planes that are actually +@@ -3379,13 +3386,16 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, + + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); + +- result->plane_en[i] = skl_compute_plane_wm(dev_priv, +- cstate, +- intel_pstate, +- ddb_blocks, +- level, +- &result->plane_res_b[i], +- &result->plane_res_l[i]); ++ ret = skl_compute_plane_wm(dev_priv, ++ cstate, ++ intel_pstate, ++ ddb_blocks, ++ level, ++ &result->plane_res_b[i], ++ &result->plane_res_l[i], ++ &result->plane_en[i]); ++ if (ret) ++ return ret; + } + + return 0; +@@ -3422,21 +3432,26 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, + } + } + +-static void skl_build_pipe_wm(struct intel_crtc_state *cstate, +- struct skl_ddb_allocation *ddb, +- struct skl_pipe_wm *pipe_wm) ++static int skl_build_pipe_wm(struct intel_crtc_state *cstate, ++ struct skl_ddb_allocation *ddb, ++ struct skl_pipe_wm *pipe_wm) + { + struct drm_device *dev = cstate->base.crtc->dev; + const struct drm_i915_private *dev_priv = dev->dev_private; + int level, max_level = ilk_wm_max_level(dev); ++ int ret; + + for (level = 0; level <= max_level; level++) { +- skl_compute_wm_level(dev_priv, ddb, cstate, +- level, &pipe_wm->wm[level]); ++ ret = skl_compute_wm_level(dev_priv, ddb, cstate, ++ level, &pipe_wm->wm[level]); ++ if (ret) ++ return ret; + } + pipe_wm->linetime = skl_compute_linetime_wm(cstate); + + skl_compute_transition_wm(cstate, &pipe_wm->trans_wm); ++ ++ return 0; + } + + static void skl_compute_wm_results(struct drm_device *dev, +@@ -3683,21 +3698,27 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv, + } + } + +-static bool skl_update_pipe_wm(struct drm_crtc_state *cstate, +- struct skl_ddb_allocation *ddb, /* out */ +- struct skl_pipe_wm *pipe_wm /* out */) ++static int skl_update_pipe_wm(struct drm_crtc_state *cstate, ++ struct skl_ddb_allocation *ddb, /* out */ ++ struct skl_pipe_wm *pipe_wm, /* out */ ++ bool *changed /* out */) + { + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc); + struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate); ++ int ret; + +- skl_build_pipe_wm(intel_cstate, ddb, pipe_wm); ++ ret = skl_build_pipe_wm(intel_cstate, ddb, pipe_wm); ++ if (ret) ++ return ret; + + if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) +- return false; ++ *changed = false; ++ else ++ *changed = true; + + intel_crtc->wm.active.skl = *pipe_wm; + +- return true; ++ return 0; + } + + static void skl_update_other_pipe_wm(struct drm_device *dev, +@@ -3730,8 +3751,8 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, + if (!intel_crtc->active) + continue; + +- wm_changed = skl_update_pipe_wm(intel_crtc->base.state, +- &r->ddb, &pipe_wm); ++ skl_update_pipe_wm(intel_crtc->base.state, ++ &r->ddb, &pipe_wm, &wm_changed); + + /* + * If we end up re-computing the other pipe WM values, it's +@@ -3841,14 +3862,15 @@ static void skl_update_wm(struct drm_crtc *crtc) + struct skl_wm_values *results = &dev_priv->wm.skl_results; + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; +- ++ bool wm_changed; + + /* Clear all dirty flags */ + results->dirty_pipes = 0; + + skl_clear_wm(results, intel_crtc->pipe); + +- if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm)) ++ skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed); ++ if (!wm_changed) + return; + + skl_compute_wm_results(dev, pipe_wm, results, intel_crtc); +-- +2.7.4 + |