aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c59
2 files changed, 60 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1e05da992aa0..9bab6124cde8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -538,6 +538,8 @@ struct intel_crtc_wm_state {
538 struct { 538 struct {
539 /* "raw" watermarks (not inverted) */ 539 /* "raw" watermarks (not inverted) */
540 struct vlv_pipe_wm raw[NUM_VLV_WM_LEVELS]; 540 struct vlv_pipe_wm raw[NUM_VLV_WM_LEVELS];
541 /* intermediate watermarks (inverted) */
542 struct vlv_wm_state intermediate;
541 /* optimal watermarks (inverted) */ 543 /* optimal watermarks (inverted) */
542 struct vlv_wm_state optimal; 544 struct vlv_wm_state optimal;
543 /* display FIFO split */ 545 /* display FIFO split */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 39bc4206be7a..824d5b0806b9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1401,6 +1401,45 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
1401 1401
1402#undef VLV_FIFO 1402#undef VLV_FIFO
1403 1403
1404static int vlv_compute_intermediate_wm(struct drm_device *dev,
1405 struct intel_crtc *crtc,
1406 struct intel_crtc_state *crtc_state)
1407{
1408 struct vlv_wm_state *intermediate = &crtc_state->wm.vlv.intermediate;
1409 const struct vlv_wm_state *optimal = &crtc_state->wm.vlv.optimal;
1410 const struct vlv_wm_state *active = &crtc->wm.active.vlv;
1411 int level;
1412
1413 intermediate->num_levels = min(optimal->num_levels, active->num_levels);
1414 intermediate->cxsr = optimal->cxsr & active->cxsr;
1415
1416 for (level = 0; level < intermediate->num_levels; level++) {
1417 enum plane_id plane_id;
1418
1419 for_each_plane_id_on_crtc(crtc, plane_id) {
1420 intermediate->wm[level].plane[plane_id] =
1421 min(optimal->wm[level].plane[plane_id],
1422 active->wm[level].plane[plane_id]);
1423 }
1424
1425 intermediate->sr[level].plane = min(optimal->sr[level].plane,
1426 active->sr[level].plane);
1427 intermediate->sr[level].cursor = min(optimal->sr[level].cursor,
1428 active->sr[level].cursor);
1429 }
1430
1431 vlv_invalidate_wms(crtc, intermediate, level);
1432
1433 /*
1434 * If our intermediate WM are identical to the final WM, then we can
1435 * omit the post-vblank programming; only update if it's different.
1436 */
1437 if (memcmp(intermediate, optimal, sizeof(*intermediate)) == 0)
1438 crtc_state->wm.need_postvbl_update = false;
1439
1440 return 0;
1441}
1442
1404static void vlv_merge_wm(struct drm_i915_private *dev_priv, 1443static void vlv_merge_wm(struct drm_i915_private *dev_priv,
1405 struct vlv_wm_values *wm) 1444 struct vlv_wm_values *wm)
1406{ 1445{
@@ -1494,7 +1533,22 @@ static void vlv_initial_watermarks(struct intel_atomic_state *state,
1494 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); 1533 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
1495 1534
1496 mutex_lock(&dev_priv->wm.wm_mutex); 1535 mutex_lock(&dev_priv->wm.wm_mutex);
1497 crtc->wm.active.vlv = crtc_state->wm.vlv.optimal; 1536 crtc->wm.active.vlv = crtc_state->wm.vlv.intermediate;
1537 vlv_program_watermarks(dev_priv);
1538 mutex_unlock(&dev_priv->wm.wm_mutex);
1539}
1540
1541static void vlv_optimize_watermarks(struct intel_atomic_state *state,
1542 struct intel_crtc_state *crtc_state)
1543{
1544 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
1545 struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
1546
1547 if (!crtc_state->wm.need_postvbl_update)
1548 return;
1549
1550 mutex_lock(&dev_priv->wm.wm_mutex);
1551 intel_crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
1498 vlv_program_watermarks(dev_priv); 1552 vlv_program_watermarks(dev_priv);
1499 mutex_unlock(&dev_priv->wm.wm_mutex); 1553 mutex_unlock(&dev_priv->wm.wm_mutex);
1500} 1554}
@@ -4695,6 +4749,7 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
4695 vlv_invalidate_wms(crtc, active, level); 4749 vlv_invalidate_wms(crtc, active, level);
4696 4750
4697 crtc_state->wm.vlv.optimal = *active; 4751 crtc_state->wm.vlv.optimal = *active;
4752 crtc_state->wm.vlv.intermediate = *active;
4698 4753
4699 DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n", 4754 DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n",
4700 pipe_name(pipe), 4755 pipe_name(pipe),
@@ -7861,7 +7916,9 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
7861 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 7916 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
7862 vlv_setup_wm_latency(dev_priv); 7917 vlv_setup_wm_latency(dev_priv);
7863 dev_priv->display.compute_pipe_wm = vlv_compute_pipe_wm; 7918 dev_priv->display.compute_pipe_wm = vlv_compute_pipe_wm;
7919 dev_priv->display.compute_intermediate_wm = vlv_compute_intermediate_wm;
7864 dev_priv->display.initial_watermarks = vlv_initial_watermarks; 7920 dev_priv->display.initial_watermarks = vlv_initial_watermarks;
7921 dev_priv->display.optimize_watermarks = vlv_optimize_watermarks;
7865 dev_priv->display.atomic_update_watermarks = vlv_atomic_update_fifo; 7922 dev_priv->display.atomic_update_watermarks = vlv_atomic_update_fifo;
7866 } else if (IS_PINEVIEW(dev_priv)) { 7923 } else if (IS_PINEVIEW(dev_priv)) {
7867 if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv), 7924 if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),