| From 896e5bb022bce64e29ce2e1b2fc2a7476d311a15 Mon Sep 17 00:00:00 2001 |
| From: Lyude <cpaul@redhat.com> |
| Date: Wed, 24 Aug 2016 07:48:09 +0200 |
| Subject: drm/i915: Move CRTC updating in atomic_commit into it's own hook |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Lyude <cpaul@redhat.com> |
| |
| commit 896e5bb022bce64e29ce2e1b2fc2a7476d311a15 upstream. |
| |
| Since we have to write ddb allocations at the same time as we do other |
| plane updates, we're going to need to be able to control the order in |
| which we execute modesets on each pipe. The easiest way to do this is to |
| just factor this section of intel_atomic_commit_tail() |
| (intel_atomic_commit() for stable branches) into it's own function, and |
| add an appropriate display function hook for it. |
| |
| Based off of Matt Rope's suggestions |
| |
| Changes since v1: |
| - Drop pipe_config->base.active check in intel_update_crtcs() since we |
| check that before calling the function |
| |
| Signed-off-by: Lyude <cpaul@redhat.com> |
| Reviewed-by: Matt Roper <matthew.d.roper@intel.com> |
| [omitting CC for stable, since this patch will need to be changed for |
| such backports first] |
| Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| Cc: Daniel Vetter <daniel.vetter@intel.com> |
| Cc: Radhakrishna Sripada <radhakrishna.sripada@intel.com> |
| Cc: Hans de Goede <hdegoede@redhat.com> |
| Signed-off-by: Lyude <cpaul@redhat.com> |
| Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> |
| Link: http://patchwork.freedesktop.org/patch/msgid/1471961565-28540-1-git-send-email-cpaul@redhat.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/i915/i915_drv.h | 2 |
| drivers/gpu/drm/i915/intel_display.c | 74 ++++++++++++++++++++++++----------- |
| 2 files changed, 54 insertions(+), 22 deletions(-) |
| |
| --- a/drivers/gpu/drm/i915/i915_drv.h |
| +++ b/drivers/gpu/drm/i915/i915_drv.h |
| @@ -631,6 +631,8 @@ struct drm_i915_display_funcs { |
| struct intel_crtc_state *crtc_state); |
| void (*crtc_enable)(struct drm_crtc *crtc); |
| void (*crtc_disable)(struct drm_crtc *crtc); |
| + void (*update_crtcs)(struct drm_atomic_state *state, |
| + unsigned int *crtc_vblank_mask); |
| void (*audio_codec_enable)(struct drm_connector *connector, |
| struct intel_encoder *encoder, |
| const struct drm_display_mode *adjusted_mode); |
| --- a/drivers/gpu/drm/i915/intel_display.c |
| +++ b/drivers/gpu/drm/i915/intel_display.c |
| @@ -13682,6 +13682,52 @@ static bool needs_vblank_wait(struct int |
| return false; |
| } |
| |
| +static void intel_update_crtc(struct drm_crtc *crtc, |
| + struct drm_atomic_state *state, |
| + struct drm_crtc_state *old_crtc_state, |
| + unsigned int *crtc_vblank_mask) |
| +{ |
| + struct drm_device *dev = crtc->dev; |
| + struct drm_i915_private *dev_priv = to_i915(dev); |
| + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| + struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->state); |
| + bool modeset = needs_modeset(crtc->state); |
| + |
| + if (modeset) { |
| + update_scanline_offset(intel_crtc); |
| + dev_priv->display.crtc_enable(crtc); |
| + } else { |
| + intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); |
| + } |
| + |
| + if (drm_atomic_get_existing_plane_state(state, crtc->primary)) { |
| + intel_fbc_enable( |
| + intel_crtc, pipe_config, |
| + to_intel_plane_state(crtc->primary->state)); |
| + } |
| + |
| + drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); |
| + |
| + if (needs_vblank_wait(pipe_config)) |
| + *crtc_vblank_mask |= drm_crtc_mask(crtc); |
| +} |
| + |
| +static void intel_update_crtcs(struct drm_atomic_state *state, |
| + unsigned int *crtc_vblank_mask) |
| +{ |
| + struct drm_crtc *crtc; |
| + struct drm_crtc_state *old_crtc_state; |
| + int i; |
| + |
| + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { |
| + if (!crtc->state->active) |
| + continue; |
| + |
| + intel_update_crtc(crtc, state, old_crtc_state, |
| + crtc_vblank_mask); |
| + } |
| +} |
| + |
| static void intel_atomic_commit_tail(struct drm_atomic_state *state) |
| { |
| struct drm_device *dev = state->dev; |
| @@ -13780,17 +13826,9 @@ static void intel_atomic_commit_tail(str |
| intel_modeset_verify_disabled(dev); |
| } |
| |
| - /* Now enable the clocks, plane, pipe, and connectors that we set up. */ |
| + /* Complete the events for pipes that have now been disabled */ |
| for_each_crtc_in_state(state, crtc, old_crtc_state, i) { |
| - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| bool modeset = needs_modeset(crtc->state); |
| - struct intel_crtc_state *pipe_config = |
| - to_intel_crtc_state(crtc->state); |
| - |
| - if (modeset && crtc->state->active) { |
| - update_scanline_offset(to_intel_crtc(crtc)); |
| - dev_priv->display.crtc_enable(crtc); |
| - } |
| |
| /* Complete events for now disable pipes here. */ |
| if (modeset && !crtc->state->active && crtc->state->event) { |
| @@ -13800,21 +13838,11 @@ static void intel_atomic_commit_tail(str |
| |
| crtc->state->event = NULL; |
| } |
| - |
| - if (!modeset) |
| - intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); |
| - |
| - if (crtc->state->active && |
| - drm_atomic_get_existing_plane_state(state, crtc->primary)) |
| - intel_fbc_enable(intel_crtc, pipe_config, to_intel_plane_state(crtc->primary->state)); |
| - |
| - if (crtc->state->active) |
| - drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); |
| - |
| - if (pipe_config->base.active && needs_vblank_wait(pipe_config)) |
| - crtc_vblank_mask |= 1 << i; |
| } |
| |
| + /* Now enable the clocks, plane, pipe, and connectors that we set up. */ |
| + dev_priv->display.update_crtcs(state, &crtc_vblank_mask); |
| + |
| /* FIXME: We should call drm_atomic_helper_commit_hw_done() here |
| * already, but still need the state for the delayed optimization. To |
| * fix this: |
| @@ -15275,6 +15303,8 @@ void intel_init_display_hooks(struct drm |
| dev_priv->display.crtc_disable = i9xx_crtc_disable; |
| } |
| |
| + dev_priv->display.update_crtcs = intel_update_crtcs; |
| + |
| /* Returns the core display clock speed */ |
| if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| dev_priv->display.get_display_clock_speed = |