diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 59 |
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 | ||
1404 | static 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 | |||
1404 | static void vlv_merge_wm(struct drm_i915_private *dev_priv, | 1443 | static 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 | |||
1541 | static 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), |