Commit cf1f697a authored by Mahesh Kumar's avatar Mahesh Kumar Committed by Maarten Lankhorst

drm/i915/skl: distribute DDB based on panel resolution

We distribute DDB equally among all pipes irrespective of display
buffer requirement of each pipe. This leads to a situation where high
resolution y-tiled display can not be enabled with 2 low resolution
displays.

Main contributing factor for DDB requirement is width of the display.
This patch make changes to distribute ddb based on display width.
So display with higher width will get bigger chunk of DDB.

Changes Since V1:
 - pipe_size/ddb_size will not overflow u16 so use appropriate
   data-types during computation (Chris)
Changes Since V2:
 - avoid redundancy and possible truncation errors (Chris)

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107113
Cc: raviraj.p.sitaram@intel.com
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarMahesh Kumar <mahesh1.kumar@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180801151113.5337-1-mahesh1.kumar@intel.com
parent aaa02378
...@@ -3814,8 +3814,12 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, ...@@ -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 intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *for_crtc = cstate->base.crtc; struct drm_crtc *for_crtc = cstate->base.crtc;
u16 pipe_size, ddb_size; const struct drm_crtc_state *crtc_state;
int nth_active_pipe; 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) { if (WARN_ON(!state) || !cstate->base.active) {
alloc->start = 0; alloc->start = 0;
...@@ -3833,14 +3837,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, ...@@ -3833,14 +3837,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
*num_active, ddb); *num_active, ddb);
/* /*
* If the state doesn't change the active CRTC's, then there's * If the state doesn't change the active CRTC's or there is no
* no need to recalculate; the existing pipe allocation limits * modeset request, then there's no need to recalculate;
* should remain unchanged. Note that we're safe from racing * the existing pipe allocation limits should remain unchanged.
* commits since any racing commit that changes the active CRTC * Note that we're safe from racing commits since any racing commit
* list would need to grab _all_ crtc locks, including the one * that changes the active CRTC list or do modeset would need to
* we currently hold. * 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, * alloc may be cleared by clear_intel_crtc_state,
* copy from old state to be sure * copy from old state to be sure
...@@ -3849,11 +3853,32 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, ...@@ -3849,11 +3853,32 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
return; return;
} }
nth_active_pipe = hweight32(intel_state->active_crtcs & /*
(drm_crtc_mask(for_crtc) - 1)); * Watermark/ddb requirement highly depends upon width of the
pipe_size = ddb_size / hweight32(intel_state->active_crtcs); * framebuffer, So instead of allocating DDB equally among pipes
alloc->start = nth_active_pipe * ddb_size / *num_active; * distribute DDB based on resolution/width of the display.
alloc->end = alloc->start + pipe_size; */
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) 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) ...@@ -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 * any other display updates race with this transaction, so we need
* to grab the lock on *all* CRTC's. * 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; realloc_pipes = ~0;
intel_state->wm_results.dirty_pipes = ~0; intel_state->wm_results.dirty_pipes = ~0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment