aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Roper <matthew.d.roper@intel.com>2016-05-12 10:06:08 -0400
committerMatt Roper <matthew.d.roper@intel.com>2016-05-13 10:34:48 -0400
commit55994c2c38a1101f84cdf277b228f830af8a9c1b (patch)
tree707c03aac8ae589b8261607b7461fad888d944e3
parent2b4b9f35d94b1b533bc23110b040b04316480b28 (diff)
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
-rw-r--r--drivers/gpu/drm/i915/intel_display.c10
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c90
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 325e75f881a2..94804d992cd1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13309,7 +13309,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
13309 * phase. The code here should be run after the per-crtc and per-plane 'check' 13309 * phase. The code here should be run after the per-crtc and per-plane 'check'
13310 * handlers to ensure that all derived state has been updated. 13310 * handlers to ensure that all derived state has been updated.
13311 */ 13311 */
13312static void calc_watermark_data(struct drm_atomic_state *state) 13312static int calc_watermark_data(struct drm_atomic_state *state)
13313{ 13313{
13314 struct drm_device *dev = state->dev; 13314 struct drm_device *dev = state->dev;
13315 struct drm_i915_private *dev_priv = to_i915(dev); 13315 struct drm_i915_private *dev_priv = to_i915(dev);
@@ -13345,7 +13345,9 @@ static void calc_watermark_data(struct drm_atomic_state *state)
13345 13345
13346 /* Is there platform-specific watermark information to calculate? */ 13346 /* Is there platform-specific watermark information to calculate? */
13347 if (dev_priv->display.compute_global_watermarks) 13347 if (dev_priv->display.compute_global_watermarks)
13348 dev_priv->display.compute_global_watermarks(state); 13348 return dev_priv->display.compute_global_watermarks(state);
13349
13350 return 0;
13349} 13351}
13350 13352
13351/** 13353/**
@@ -13432,9 +13434,7 @@ static int intel_atomic_check(struct drm_device *dev,
13432 return ret; 13434 return ret;
13433 13435
13434 intel_fbc_choose_crtc(dev_priv, state); 13436 intel_fbc_choose_crtc(dev_priv, state);
13435 calc_watermark_data(state); 13437 return calc_watermark_data(state);
13436
13437 return 0;
13438} 13438}
13439 13439
13440static int intel_atomic_prepare_commit(struct drm_device *dev, 13440static 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 14c2c3e25ef8..1d8407a8fd34 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,
3238 return false; 3238 return false;
3239} 3239}
3240 3240
3241static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, 3241static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
3242 struct intel_crtc_state *cstate, 3242 struct intel_crtc_state *cstate,
3243 struct intel_plane_state *intel_pstate, 3243 struct intel_plane_state *intel_pstate,
3244 uint16_t ddb_allocation, 3244 uint16_t ddb_allocation,
3245 int level, 3245 int level,
3246 uint16_t *out_blocks, /* out */ 3246 uint16_t *out_blocks, /* out */
3247 uint8_t *out_lines /* out */) 3247 uint8_t *out_lines, /* out */
3248 bool *enabled /* out */)
3248{ 3249{
3249 struct drm_plane_state *pstate = &intel_pstate->base; 3250 struct drm_plane_state *pstate = &intel_pstate->base;
3250 struct drm_framebuffer *fb = pstate->fb; 3251 struct drm_framebuffer *fb = pstate->fb;
@@ -3256,8 +3257,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
3256 uint8_t cpp; 3257 uint8_t cpp;
3257 uint32_t width = 0, height = 0; 3258 uint32_t width = 0, height = 0;
3258 3259
3259 if (latency == 0 || !cstate->base.active || !intel_pstate->visible) 3260 if (latency == 0 || !cstate->base.active || !intel_pstate->visible) {
3260 return false; 3261 *enabled = false;
3262 return 0;
3263 }
3261 3264
3262 width = drm_rect_width(&intel_pstate->src) >> 16; 3265 width = drm_rect_width(&intel_pstate->src) >> 16;
3263 height = drm_rect_height(&intel_pstate->src) >> 16; 3266 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,
3318 res_blocks++; 3321 res_blocks++;
3319 } 3322 }
3320 3323
3321 if (res_blocks >= ddb_allocation || res_lines > 31) 3324 if (res_blocks >= ddb_allocation || res_lines > 31) {
3322 return false; 3325 *enabled = false;
3326 return 0;
3327 }
3323 3328
3324 *out_blocks = res_blocks; 3329 *out_blocks = res_blocks;
3325 *out_lines = res_lines; 3330 *out_lines = res_lines;
3331 *enabled = true;
3326 3332
3327 return true; 3333 return 0;
3328} 3334}
3329 3335
3330static int 3336static int
@@ -3342,6 +3348,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
3342 struct intel_plane_state *intel_pstate; 3348 struct intel_plane_state *intel_pstate;
3343 uint16_t ddb_blocks; 3349 uint16_t ddb_blocks;
3344 enum pipe pipe = intel_crtc->pipe; 3350 enum pipe pipe = intel_crtc->pipe;
3351 int ret;
3345 3352
3346 /* 3353 /*
3347 * We'll only calculate watermarks for planes that are actually 3354 * 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,
3379 3386
3380 ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); 3387 ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
3381 3388
3382 result->plane_en[i] = skl_compute_plane_wm(dev_priv, 3389 ret = skl_compute_plane_wm(dev_priv,
3383 cstate, 3390 cstate,
3384 intel_pstate, 3391 intel_pstate,
3385 ddb_blocks, 3392 ddb_blocks,
3386 level, 3393 level,
3387 &result->plane_res_b[i], 3394 &result->plane_res_b[i],
3388 &result->plane_res_l[i]); 3395 &result->plane_res_l[i],
3396 &result->plane_en[i]);
3397 if (ret)
3398 return ret;
3389 } 3399 }
3390 3400
3391 return 0; 3401 return 0;
@@ -3422,21 +3432,26 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
3422 } 3432 }
3423} 3433}
3424 3434
3425static void skl_build_pipe_wm(struct intel_crtc_state *cstate, 3435static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
3426 struct skl_ddb_allocation *ddb, 3436 struct skl_ddb_allocation *ddb,
3427 struct skl_pipe_wm *pipe_wm) 3437 struct skl_pipe_wm *pipe_wm)
3428{ 3438{
3429 struct drm_device *dev = cstate->base.crtc->dev; 3439 struct drm_device *dev = cstate->base.crtc->dev;
3430 const struct drm_i915_private *dev_priv = dev->dev_private; 3440 const struct drm_i915_private *dev_priv = dev->dev_private;
3431 int level, max_level = ilk_wm_max_level(dev); 3441 int level, max_level = ilk_wm_max_level(dev);
3442 int ret;
3432 3443
3433 for (level = 0; level <= max_level; level++) { 3444 for (level = 0; level <= max_level; level++) {
3434 skl_compute_wm_level(dev_priv, ddb, cstate, 3445 ret = skl_compute_wm_level(dev_priv, ddb, cstate,
3435 level, &pipe_wm->wm[level]); 3446 level, &pipe_wm->wm[level]);
3447 if (ret)
3448 return ret;
3436 } 3449 }
3437 pipe_wm->linetime = skl_compute_linetime_wm(cstate); 3450 pipe_wm->linetime = skl_compute_linetime_wm(cstate);
3438 3451
3439 skl_compute_transition_wm(cstate, &pipe_wm->trans_wm); 3452 skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
3453
3454 return 0;
3440} 3455}
3441 3456
3442static void skl_compute_wm_results(struct drm_device *dev, 3457static 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,
3683 } 3698 }
3684} 3699}
3685 3700
3686static bool skl_update_pipe_wm(struct drm_crtc_state *cstate, 3701static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
3687 struct skl_ddb_allocation *ddb, /* out */ 3702 struct skl_ddb_allocation *ddb, /* out */
3688 struct skl_pipe_wm *pipe_wm /* out */) 3703 struct skl_pipe_wm *pipe_wm, /* out */
3704 bool *changed /* out */)
3689{ 3705{
3690 struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc); 3706 struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
3691 struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate); 3707 struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
3708 int ret;
3692 3709
3693 skl_build_pipe_wm(intel_cstate, ddb, pipe_wm); 3710 ret = skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
3711 if (ret)
3712 return ret;
3694 3713
3695 if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) 3714 if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
3696 return false; 3715 *changed = false;
3716 else
3717 *changed = true;
3697 3718
3698 intel_crtc->wm.active.skl = *pipe_wm; 3719 intel_crtc->wm.active.skl = *pipe_wm;
3699 3720
3700 return true; 3721 return 0;
3701} 3722}
3702 3723
3703static void skl_update_other_pipe_wm(struct drm_device *dev, 3724static 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,
3730 if (!intel_crtc->active) 3751 if (!intel_crtc->active)
3731 continue; 3752 continue;
3732 3753
3733 wm_changed = skl_update_pipe_wm(intel_crtc->base.state, 3754 skl_update_pipe_wm(intel_crtc->base.state,
3734 &r->ddb, &pipe_wm); 3755 &r->ddb, &pipe_wm, &wm_changed);
3735 3756
3736 /* 3757 /*
3737 * If we end up re-computing the other pipe WM values, it's 3758 * 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)
3841 struct skl_wm_values *results = &dev_priv->wm.skl_results; 3862 struct skl_wm_values *results = &dev_priv->wm.skl_results;
3842 struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); 3863 struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
3843 struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; 3864 struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
3844 3865 bool wm_changed;
3845 3866
3846 /* Clear all dirty flags */ 3867 /* Clear all dirty flags */
3847 results->dirty_pipes = 0; 3868 results->dirty_pipes = 0;
3848 3869
3849 skl_clear_wm(results, intel_crtc->pipe); 3870 skl_clear_wm(results, intel_crtc->pipe);
3850 3871
3851 if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm)) 3872 skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed);
3873 if (!wm_changed)
3852 return; 3874 return;
3853 3875
3854 skl_compute_wm_results(dev, pipe_wm, results, intel_crtc); 3876 skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);