Op 09-09-2019 om 17:52 schreef Manasi Navare:
> As per the display enable sequence, we need to follow the enable sequence
> for slaves first with DP_TP_CTL set to Idle and configure the transcoder
> port sync register to select the corersponding master, then follow the
> enable sequence for master leaving DP_TP_CTL to idle.
> At this point the transcoder port sync mode is configured and enabled
> and the Vblanks of both ports are synchronized so then set DP_TP_CTL
> for the slave and master to Normal and do post crtc enable updates.
>
> v5:
> * Fix checkpatch warning (Manasi)
> v4:
> * Reuse skl_commit_modeset_enables() hook (Maarten)
> * Obtain slave crtc and states from master (Maarten)
> v3:
> * Rebase on drm-tip (Manasi)
> v2:
> * Create a icl_update_crtcs hook (Maarten, Danvet)
> * This sequence only for CRTCs in trans port sync mode (Maarten)
>
> Cc: Daniel Vetter <daniel.vet...@ffwll.ch>
> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com>
> Cc: Maarten Lankhorst <maarten.lankho...@linux.intel.com>
> Cc: Matt Roper <matthew.d.ro...@intel.com>
> Signed-off-by: Manasi Navare <manasi.d.nav...@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c     |   3 +-
>  drivers/gpu/drm/i915/display/intel_display.c | 158 ++++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_display.h |   4 +
>  3 files changed, 162 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
> b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 3e6394139964..62e9f5602b6b 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -3347,7 +3347,8 @@ static void hsw_ddi_pre_enable_dp(struct intel_encoder 
> *encoder,
>                                             true);
>       intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
>       intel_dp_start_link_train(intel_dp);
> -     if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
> +     if ((port != PORT_A || INTEL_GEN(dev_priv) >= 9) &&
> +         !is_trans_port_sync_mode(dev_priv, crtc_state))
>               intel_dp_stop_link_train(intel_dp);
>  
>       intel_ddi_enable_fec(encoder, crtc_state);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 76ca1ca864c0..5e583e9157f0 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -521,6 +521,24 @@ needs_modeset(const struct intel_crtc_state *state)
>       return drm_atomic_crtc_needs_modeset(&state->base);
>  }
>  
> +bool
> +is_trans_port_sync_mode(struct drm_i915_private *dev_priv,
> +                     const struct intel_crtc_state *state)
> +{
> +     return (INTEL_GEN(dev_priv) >= 11 &&
> +             (state->master_transcoder != INVALID_TRANSCODER ||
> +              state->sync_mode_slaves_mask));
> +}
> +
> +static bool
> +is_trans_port_sync_master(struct drm_i915_private *dev_priv,
> +                       const struct intel_crtc_state *state)
> +{
> +     return (INTEL_GEN(dev_priv) >= 11 &&
> +             (state->master_transcoder == INVALID_TRANSCODER &&
> +              state->sync_mode_slaves_mask));
> +}
> +
>  /*
>   * Platform specific helpers to calculate the port PLL loopback- (clock.m),
>   * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
> @@ -13974,6 +13992,30 @@ static void intel_update_crtc(struct intel_crtc 
> *crtc,
>       intel_finish_crtc_commit(state, crtc);
>  }
>  
> +static struct intel_crtc *intel_get_slave_crtc(struct drm_i915_private 
> *dev_priv,
> +                                            struct intel_crtc_state 
> *new_crtc_state)
> +{
> +     if (new_crtc_state->sync_mode_slaves_mask &
> +         BIT(TRANSCODER_A))
> +             return intel_get_crtc_for_pipe(dev_priv,
> +                                            PIPE_A);
> +     else if (new_crtc_state->sync_mode_slaves_mask &
> +              BIT(TRANSCODER_B))
> +             return intel_get_crtc_for_pipe(dev_priv,
> +                                            PIPE_B);
> +     else if (new_crtc_state->sync_mode_slaves_mask &
> +              BIT(TRANSCODER_C))
> +             return intel_get_crtc_for_pipe(dev_priv,
> +                                            PIPE_C);
> +     else if (new_crtc_state->sync_mode_slaves_mask &
> +              BIT(TRANSCODER_D))
> +             return intel_get_crtc_for_pipe(dev_priv,
> +                                            PIPE_D);
> +     /* should never happen */
> +     WARN_ON(1);
> +     return NULL;
> +}
> +
>  static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
>                                         struct intel_crtc_state 
> *old_crtc_state,
>                                         struct intel_crtc_state 
> *new_crtc_state,
> @@ -14052,6 +14094,104 @@ static void intel_commit_modeset_enables(struct 
> intel_atomic_state *state)
>       }
>  }
>  
> +static void intel_crtc_enable_trans_port_sync(struct intel_crtc *crtc,
> +                                           struct intel_atomic_state *state,
> +                                           struct intel_crtc_state 
> *new_crtc_state)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> +
> +     update_scanline_offset(new_crtc_state);
> +     dev_priv->display.crtc_enable(new_crtc_state, state);
> +     intel_crtc_enable_pipe_crc(crtc);
> +}
> +
> +static void intel_set_dp_tp_ctl_normal(struct intel_crtc *crtc,
> +                                    struct intel_atomic_state *state)
> +{
> +     struct drm_connector_state *conn_state;
> +     struct drm_connector *conn;
> +     struct intel_dp *intel_dp;
> +     int i;
> +
> +     for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
> +             if (conn_state->crtc == &crtc->base)
> +                     break;
> +     }
> +     intel_dp = enc_to_intel_dp(&intel_attached_encoder(conn)->base);
> +     intel_dp_stop_link_train(intel_dp);
> +}
> +
> +static void intel_post_crtc_enable_updates(struct intel_crtc *crtc,
> +                                        struct intel_atomic_state *state,
> +                                        struct intel_crtc_state 
> *old_crtc_state,
> +                                        struct intel_crtc_state 
> *new_crtc_state)
> +{
> +     struct intel_plane_state *new_plane_state =
> +             intel_atomic_get_new_plane_state(state,
> +                                              
> to_intel_plane(crtc->base.primary));
> +
> +     if (new_crtc_state->update_pipe && !new_crtc_state->enable_fbc)
> +             intel_fbc_disable(crtc);
> +     else if (new_plane_state)
> +             intel_fbc_enable(crtc, new_crtc_state, new_plane_state);
> +
> +     intel_begin_crtc_commit(state, crtc);
> +     skl_update_planes_on_crtc(state, crtc);
> +     intel_finish_crtc_commit(state, crtc);
> +}
> +
> +static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
> +                                            struct intel_atomic_state *state,
> +                                            struct intel_crtc_state 
> *old_crtc_state,
> +                                            struct intel_crtc_state 
> *new_crtc_state)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> +     struct intel_crtc *slave_crtc = intel_get_slave_crtc(dev_priv,
> +                                                          new_crtc_state);
> +     struct intel_crtc_state *new_slave_crtc_state =
> +             intel_atomic_get_new_crtc_state(state, slave_crtc);
> +     struct intel_crtc_state *old_slave_crtc_state =
> +             intel_atomic_get_old_crtc_state(state, slave_crtc);
> +
> +     WARN_ON(!slave_crtc || !new_slave_crtc_state ||
> +             !old_slave_crtc_state);
> +
> +     DRM_DEBUG_KMS("Updating Transcoder Port Sync Master CRTC = %d %s and 
> Slave CRTC %d %s\n",
> +                   crtc->base.base.id, crtc->base.name, 
> slave_crtc->base.base.id,
> +                   slave_crtc->base.name);
> +
> +     /* Enable seq for slave with with DP_TP_CTL left Idle until the
> +      * master is ready
> +      */
> +     intel_crtc_enable_trans_port_sync(slave_crtc,
> +                                       state,
> +                                       new_slave_crtc_state);
> +
> +     /* Enable seq for master with with DP_TP_CTL left Idle */
> +     intel_crtc_enable_trans_port_sync(crtc,
> +                                       state,
> +                                       new_crtc_state);
> +
> +     /* Set Slave's DP_TP_CTL to Normal */
> +     intel_set_dp_tp_ctl_normal(slave_crtc,
> +                                state);
> +
> +     /* Set Master's DP_TP_CTL To Normal */
> +     usleep_range(200, 400);
> +     intel_set_dp_tp_ctl_normal(crtc,
> +                                state);
> +
> +     /* Now do the post crtc enable for all master and slaves */
> +     intel_post_crtc_enable_updates(slave_crtc,
> +                                    state,
> +                                    new_slave_crtc_state,
> +                                    old_slave_crtc_state);
> +     intel_post_crtc_enable_updates(crtc,
> +                                    state,
> +                                    new_crtc_state,
> +                                    old_crtc_state);
> +}

Looks sort of like what I had in mind. :)

As a patch 7/6, you should really have a function like intel_update_bigjoiner in

https://patchwork.freedesktop.org/patch/331201/?series=66802&rev=1

This will ensure tear-free updates when using atomic to update both. But it 
would be something that can be done more easily after bigjoiner work has landed.

>  static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  {
>       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> @@ -14086,6 +14226,7 @@ static void skl_commit_modeset_enables(struct 
> intel_atomic_state *state)
>               for_each_oldnew_intel_crtc_in_state(state, crtc, 
> old_crtc_state, new_crtc_state, i) {
>                       bool vbl_wait = false;
>                       unsigned int cmask = drm_crtc_mask(&crtc->base);
> +                     bool modeset = needs_modeset(new_crtc_state);
>  
>                       pipe = crtc->pipe;
>  
> @@ -14108,12 +14249,25 @@ static void skl_commit_modeset_enables(struct 
> intel_atomic_state *state)
>                        */
>                       if (!skl_ddb_entry_equal(&new_crtc_state->wm.skl.ddb,
>                                                &old_crtc_state->wm.skl.ddb) &&
> +                         !modeset &&
>                           !new_crtc_state->base.active_changed &&
!modeset implies !active_changed, but with this fixed looks good.
>                           state->wm_results.dirty_pipes != updated)
>                               vbl_wait = true;
>  
> -                     intel_update_crtc(crtc, state, old_crtc_state,
> -                                       new_crtc_state);
> +                     if (modeset && is_trans_port_sync_mode(dev_priv,
> +                                                            new_crtc_state)) 
> {
> +                             if (is_trans_port_sync_master(dev_priv,
> +                                                           new_crtc_state))
> +                                     intel_update_trans_port_sync_crtcs(crtc,
> +                                                                        
> state,
> +                                                                        
> old_crtc_state,
> +                                                                        
> new_crtc_state);
> +                             else
> +                                     continue;
Yeah, this looks as I expect it to. :)
> +                     } else {
> +                             intel_update_crtc(crtc, state, old_crtc_state,
> +                                               new_crtc_state);
> +                     }
>  
>                       if (vbl_wait)
>                               intel_wait_for_vblank(dev_priv, pipe);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
> b/drivers/gpu/drm/i915/display/intel_display.h
> index c1011204b407..3e0a36ec580d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -27,6 +27,7 @@
>  
>  #include <drm/drm_util.h>
>  #include <drm/i915_drm.h>
> +#include "intel_dp_link_training.h"
>  
>  enum link_m_n_set;
>  struct dpll;
> @@ -52,6 +53,7 @@ struct intel_plane;
>  struct intel_plane_state;
>  struct intel_remapped_info;
>  struct intel_rotation_info;
> +struct intel_crtc_state;
>  
>  enum i915_gpio {
>       GPIOA,
> @@ -449,6 +451,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private 
> *dev_priv,
>                             u32 pixel_format, u64 modifier);
>  bool intel_plane_can_remap(const struct intel_plane_state *plane_state);
>  enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port);
> +bool is_trans_port_sync_mode(struct drm_i915_private *i915,
> +                          const struct intel_crtc_state *state);
>  
>  void intel_plane_destroy(struct drm_plane *plane);
>  void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to