Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Mahesh Kumar <mahesh1.kumar@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180801151113.5337-1-mahesh1.kumar@intel.com

authored by

Mahesh Kumar and committed by
Maarten Lankhorst
cf1f697a aaa02378

+40 -15
+40 -15
drivers/gpu/drm/i915/intel_pm.c
··· 3814 3814 struct intel_atomic_state *intel_state = to_intel_atomic_state(state); 3815 3815 struct drm_i915_private *dev_priv = to_i915(dev); 3816 3816 struct drm_crtc *for_crtc = cstate->base.crtc; 3817 - u16 pipe_size, ddb_size; 3818 - int nth_active_pipe; 3817 + const struct drm_crtc_state *crtc_state; 3818 + const struct drm_crtc *crtc; 3819 + u32 pipe_width = 0, total_width = 0, width_before_pipe = 0; 3820 + enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe; 3821 + u16 ddb_size; 3822 + u32 i; 3819 3823 3820 3824 if (WARN_ON(!state) || !cstate->base.active) { 3821 3825 alloc->start = 0; ··· 3837 3833 *num_active, ddb); 3838 3834 3839 3835 /* 3840 - * If the state doesn't change the active CRTC's, then there's 3841 - * no need to recalculate; the existing pipe allocation limits 3842 - * should remain unchanged. Note that we're safe from racing 3843 - * commits since any racing commit that changes the active CRTC 3844 - * list would need to grab _all_ crtc locks, including the one 3845 - * we currently hold. 3836 + * If the state doesn't change the active CRTC's or there is no 3837 + * modeset request, then there's no need to recalculate; 3838 + * the existing pipe allocation limits should remain unchanged. 3839 + * Note that we're safe from racing commits since any racing commit 3840 + * that changes the active CRTC list or do modeset would need to 3841 + * grab _all_ crtc locks, including the one we currently hold. 3846 3842 */ 3847 - if (!intel_state->active_pipe_changes) { 3843 + if (!intel_state->active_pipe_changes && !intel_state->modeset) { 3848 3844 /* 3849 3845 * alloc may be cleared by clear_intel_crtc_state, 3850 3846 * copy from old state to be sure ··· 3853 3849 return; 3854 3850 } 3855 3851 3856 - nth_active_pipe = hweight32(intel_state->active_crtcs & 3857 - (drm_crtc_mask(for_crtc) - 1)); 3858 - pipe_size = ddb_size / hweight32(intel_state->active_crtcs); 3859 - alloc->start = nth_active_pipe * ddb_size / *num_active; 3860 - alloc->end = alloc->start + pipe_size; 3852 + /* 3853 + * Watermark/ddb requirement highly depends upon width of the 3854 + * framebuffer, So instead of allocating DDB equally among pipes 3855 + * distribute DDB based on resolution/width of the display. 3856 + */ 3857 + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { 3858 + const struct drm_display_mode *adjusted_mode; 3859 + int hdisplay, vdisplay; 3860 + enum pipe pipe; 3861 + 3862 + if (!crtc_state->enable) 3863 + continue; 3864 + 3865 + pipe = to_intel_crtc(crtc)->pipe; 3866 + adjusted_mode = &crtc_state->adjusted_mode; 3867 + drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay); 3868 + total_width += hdisplay; 3869 + 3870 + if (pipe < for_pipe) 3871 + width_before_pipe += hdisplay; 3872 + else if (pipe == for_pipe) 3873 + pipe_width = hdisplay; 3874 + } 3875 + 3876 + alloc->start = ddb_size * width_before_pipe / total_width; 3877 + alloc->end = ddb_size * (width_before_pipe + pipe_width) / total_width; 3861 3878 } 3862 3879 3863 3880 static unsigned int skl_cursor_allocation(int num_active) ··· 5279 5254 * any other display updates race with this transaction, so we need 5280 5255 * to grab the lock on *all* CRTC's. 5281 5256 */ 5282 - if (intel_state->active_pipe_changes) { 5257 + if (intel_state->active_pipe_changes || intel_state->modeset) { 5283 5258 realloc_pipes = ~0; 5284 5259 intel_state->wm_results.dirty_pipes = ~0; 5285 5260 }