|
@@ -3814,8 +3814,12 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
struct drm_crtc *for_crtc = cstate->base.crtc;
|
|
|
- u16 pipe_size, ddb_size;
|
|
|
- int nth_active_pipe;
|
|
|
+ const struct drm_crtc_state *crtc_state;
|
|
|
+ const struct drm_crtc *crtc;
|
|
|
+ u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
|
|
|
+ enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
|
|
|
+ u16 ddb_size;
|
|
|
+ u32 i;
|
|
|
|
|
|
if (WARN_ON(!state) || !cstate->base.active) {
|
|
|
alloc->start = 0;
|
|
@@ -3833,14 +3837,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
|
|
|
*num_active, ddb);
|
|
|
|
|
|
/*
|
|
|
- * If the state doesn't change the active CRTC's, then there's
|
|
|
- * no need to recalculate; the existing pipe allocation limits
|
|
|
- * should remain unchanged. Note that we're safe from racing
|
|
|
- * commits since any racing commit that changes the active CRTC
|
|
|
- * list would need to grab _all_ crtc locks, including the one
|
|
|
- * we currently hold.
|
|
|
+ * If the state doesn't change the active CRTC's or there is no
|
|
|
+ * modeset request, then there's no need to recalculate;
|
|
|
+ * the existing pipe allocation limits should remain unchanged.
|
|
|
+ * Note that we're safe from racing commits since any racing commit
|
|
|
+ * that changes the active CRTC list or do modeset would need to
|
|
|
+ * grab _all_ crtc locks, including the one we currently hold.
|
|
|
*/
|
|
|
- if (!intel_state->active_pipe_changes) {
|
|
|
+ if (!intel_state->active_pipe_changes && !intel_state->modeset) {
|
|
|
/*
|
|
|
* alloc may be cleared by clear_intel_crtc_state,
|
|
|
* copy from old state to be sure
|
|
@@ -3849,11 +3853,32 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- nth_active_pipe = hweight32(intel_state->active_crtcs &
|
|
|
- (drm_crtc_mask(for_crtc) - 1));
|
|
|
- pipe_size = ddb_size / hweight32(intel_state->active_crtcs);
|
|
|
- alloc->start = nth_active_pipe * ddb_size / *num_active;
|
|
|
- alloc->end = alloc->start + pipe_size;
|
|
|
+ /*
|
|
|
+ * Watermark/ddb requirement highly depends upon width of the
|
|
|
+ * framebuffer, So instead of allocating DDB equally among pipes
|
|
|
+ * distribute DDB based on resolution/width of the display.
|
|
|
+ */
|
|
|
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
+ const struct drm_display_mode *adjusted_mode;
|
|
|
+ int hdisplay, vdisplay;
|
|
|
+ enum pipe pipe;
|
|
|
+
|
|
|
+ if (!crtc_state->enable)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ pipe = to_intel_crtc(crtc)->pipe;
|
|
|
+ adjusted_mode = &crtc_state->adjusted_mode;
|
|
|
+ drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay);
|
|
|
+ total_width += hdisplay;
|
|
|
+
|
|
|
+ if (pipe < for_pipe)
|
|
|
+ width_before_pipe += hdisplay;
|
|
|
+ else if (pipe == for_pipe)
|
|
|
+ pipe_width = hdisplay;
|
|
|
+ }
|
|
|
+
|
|
|
+ alloc->start = ddb_size * width_before_pipe / total_width;
|
|
|
+ alloc->end = ddb_size * (width_before_pipe + pipe_width) / total_width;
|
|
|
}
|
|
|
|
|
|
static unsigned int skl_cursor_allocation(int num_active)
|
|
@@ -5254,7 +5279,7 @@ skl_ddb_add_affected_pipes(struct drm_atomic_state *state, bool *changed)
|
|
|
* any other display updates race with this transaction, so we need
|
|
|
* to grab the lock on *all* CRTC's.
|
|
|
*/
|
|
|
- if (intel_state->active_pipe_changes) {
|
|
|
+ if (intel_state->active_pipe_changes || intel_state->modeset) {
|
|
|
realloc_pipes = ~0;
|
|
|
intel_state->wm_results.dirty_pipes = ~0;
|
|
|
}
|