OSDN Git Service

Merge tag 'drm-intel-next-2020-01-14' of git://anongit.freedesktop.org/drm/drm-intel...
authorDave Airlie <airlied@redhat.com>
Wed, 15 Jan 2020 06:57:53 +0000 (16:57 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 15 Jan 2020 06:57:54 +0000 (16:57 +1000)
Final drm/i915 features for v5.6:
- DP MST fixes (José)
- Fix intel_bw_state memory leak (Pankaj Bharadiya)
- Switch context id allocation to xarray (Tvrtko)
- ICL/EHL/TGL workarounds (Matt Roper, Tvrtko)
- Debugfs for LMEM details (Lukasz Fiedorowicz)
- Prefer platform acronyms over codenames in symbols (Lucas)
- Tiled and port sync mode fixes for fbdev and DP (Manasi)
- DSI panel and backlight enable GPIO fixes (Hans de Goede)
- Relax audio min CDCLK requirements on non-GLK (Kai Vehmanen)
- Plane alignment and dimension check fixes (Imre)
- Fix state checks for PSR (José)
- Remove ICL+ clock gating programming (José)
- Static checker fixes around bool usage (Ma Feng)
- Bring back tests for self-contained headers in i915 (Masahiro Yamada)
- Fix DP MST disable sequence (Ville)
- Start converting i915 to the new drm device based logging macros (Wambui Karuga)
- Add DSI VBT I2C sequence execution (Vivek Kasireddy)
- Start using function pointers and ops structs in uc code (Michal)
- Fix PMU names to not use colons or dashes (Tvrtko)
- TGL media decompression support (DK, Imre)
- Split i915_gem_gtt.[ch] to more manageable chunks (Matthew Auld)
- Create dumb buffers in LMEM where available (Ram)
- Extend mmap support for LMEM (Abdiel)
- Selftest updates (Chris)
- Hack bump up CDCLK on TGL to avoid underruns (Stan)
- Use intel_encoder and intel_connector more instead of drm counterparts (Ville)
- Build error fixes (Zhang Xiaoxu)
- Fixes related to GPU and engine initialization/resume (Chris)
- Support for prefaulting discontiguous objects (Abdiel)
- Support discontiguous LMEM object maps (Chris)
- Various GEM and GT improvements and fixes (Chris)
- Merge pinctrl dependencies branch for the DSI GPIO updates (Jani)
- Backmerge drm-next for new logging macros (Jani)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87sgkil0v9.fsf@intel.com
1  2 
drivers/gpu/drm/i915/display/intel_dp_mst.c

@@@ -43,7 -43,7 +43,7 @@@ static int intel_dp_mst_compute_link_co
                                            struct link_config_limits *limits)
  {
        struct drm_atomic_state *state = crtc_state->uapi.state;
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_dp *intel_dp = &intel_mst->primary->dp;
        struct intel_connector *connector =
                to_intel_connector(conn_state->connector);
                crtc_state->pipe_bpp = bpp;
  
                crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
 -                                                     crtc_state->pipe_bpp);
 +                                                     crtc_state->pipe_bpp,
 +                                                     false);
  
                slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr,
 -                                                    port, crtc_state->pbn);
 +                                                    port, crtc_state->pbn, 0);
                if (slots == -EDEADLK)
                        return slots;
                if (slots >= 0)
        return 0;
  }
  
+ /*
+  * Iterate over all connectors and return the smallest transcoder in the MST
+  * stream
+  */
+ static enum transcoder
+ intel_dp_mst_master_trans_compute(struct intel_atomic_state *state,
+                                 struct intel_dp *mst_port)
+ {
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_digital_connector_state *conn_state;
+       struct intel_connector *connector;
+       enum pipe ret = I915_MAX_PIPES;
+       int i;
+       if (INTEL_GEN(dev_priv) < 12)
+               return INVALID_TRANSCODER;
+       for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
+               struct intel_crtc_state *crtc_state;
+               struct intel_crtc *crtc;
+               if (connector->mst_port != mst_port || !conn_state->base.crtc)
+                       continue;
+               crtc = to_intel_crtc(conn_state->base.crtc);
+               crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+               if (!crtc_state->uapi.active)
+                       continue;
+               /*
+                * Using crtc->pipe because crtc_state->cpu_transcoder is
+                * computed, so others CRTCs could have non-computed
+                * cpu_transcoder
+                */
+               if (crtc->pipe < ret)
+                       ret = crtc->pipe;
+       }
+       if (ret == I915_MAX_PIPES)
+               return INVALID_TRANSCODER;
+       /* Simple cast works because TGL don't have a eDP transcoder */
+       return (enum transcoder)ret;
+ }
  static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
                                       struct intel_crtc_state *pipe_config,
                                       struct drm_connector_state *conn_state)
  {
+       struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_dp *intel_dp = &intel_mst->primary->dp;
        struct intel_connector *connector =
                to_intel_connector(conn_state->connector);
  
        intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
  
+       pipe_config->mst_master_transcoder = intel_dp_mst_master_trans_compute(state, intel_dp);
+       return 0;
+ }
+ /*
+  * If one of the connectors in a MST stream needs a modeset, mark all CRTCs
+  * that shares the same MST stream as mode changed,
+  * intel_modeset_pipe_config()+intel_crtc_check_fastset() will take care to do
+  * a fastset when possible.
+  */
+ static int
+ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
+                                      struct intel_atomic_state *state)
+ {
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct drm_connector_list_iter connector_list_iter;
+       struct intel_connector *connector_iter;
+       if (INTEL_GEN(dev_priv) < 12)
+               return  0;
+       if (!intel_connector_needs_modeset(state, &connector->base))
+               return 0;
+       drm_connector_list_iter_begin(&dev_priv->drm, &connector_list_iter);
+       for_each_intel_connector_iter(connector_iter, &connector_list_iter) {
+               struct intel_digital_connector_state *conn_iter_state;
+               struct intel_crtc_state *crtc_state;
+               struct intel_crtc *crtc;
+               int ret;
+               if (connector_iter->mst_port != connector->mst_port ||
+                   connector_iter == connector)
+                       continue;
+               conn_iter_state = intel_atomic_get_digital_connector_state(state,
+                                                                          connector_iter);
+               if (IS_ERR(conn_iter_state)) {
+                       drm_connector_list_iter_end(&connector_list_iter);
+                       return PTR_ERR(conn_iter_state);
+               }
+               if (!conn_iter_state->base.crtc)
+                       continue;
+               crtc = to_intel_crtc(conn_iter_state->base.crtc);
+               crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+               if (IS_ERR(crtc_state)) {
+                       drm_connector_list_iter_end(&connector_list_iter);
+                       return PTR_ERR(crtc_state);
+               }
+               ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
+               if (ret) {
+                       drm_connector_list_iter_end(&connector_list_iter);
+                       return ret;
+               }
+               crtc_state->uapi.mode_changed = true;
+       }
+       drm_connector_list_iter_end(&connector_list_iter);
        return 0;
  }
  
  static int
  intel_dp_mst_atomic_check(struct drm_connector *connector,
-                         struct drm_atomic_state *state)
+                         struct drm_atomic_state *_state)
  {
+       struct intel_atomic_state *state = to_intel_atomic_state(_state);
        struct drm_connector_state *new_conn_state =
-               drm_atomic_get_new_connector_state(state, connector);
+               drm_atomic_get_new_connector_state(&state->base, connector);
        struct drm_connector_state *old_conn_state =
-               drm_atomic_get_old_connector_state(state, connector);
+               drm_atomic_get_old_connector_state(&state->base, connector);
        struct intel_connector *intel_connector =
                to_intel_connector(connector);
        struct drm_crtc *new_crtc = new_conn_state->crtc;
        struct drm_dp_mst_topology_mgr *mgr;
        int ret;
  
-       ret = intel_digital_connector_atomic_check(connector, state);
+       ret = intel_digital_connector_atomic_check(connector, &state->base);
+       if (ret)
+               return ret;
+       ret = intel_dp_mst_atomic_master_trans_check(intel_connector, state);
        if (ret)
                return ret;
  
         * connector
         */
        if (new_crtc) {
-               struct intel_atomic_state *intel_state =
-                       to_intel_atomic_state(state);
                struct intel_crtc *intel_crtc = to_intel_crtc(new_crtc);
                struct intel_crtc_state *crtc_state =
-                       intel_atomic_get_new_crtc_state(intel_state,
-                                                       intel_crtc);
+                       intel_atomic_get_new_crtc_state(state, intel_crtc);
  
                if (!crtc_state ||
                    !drm_atomic_crtc_needs_modeset(&crtc_state->uapi) ||
                        return 0;
        }
  
-       mgr = &enc_to_mst(old_conn_state->best_encoder)->primary->dp.mst_mgr;
-       ret = drm_dp_atomic_release_vcpi_slots(state, mgr,
+       mgr = &enc_to_mst(to_intel_encoder(old_conn_state->best_encoder))->primary->dp.mst_mgr;
+       ret = drm_dp_atomic_release_vcpi_slots(&state->base, mgr,
                                               intel_connector->port);
  
        return ret;
@@@ -207,7 -316,7 +317,7 @@@ static void intel_mst_disable_dp(struc
                                 const struct intel_crtc_state *old_crtc_state,
                                 const struct drm_connector_state *old_conn_state)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
        struct intel_connector *connector =
@@@ -231,29 -340,51 +341,51 @@@ static void intel_mst_post_disable_dp(s
                                      const struct intel_crtc_state *old_crtc_state,
                                      const struct drm_connector_state *old_conn_state)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
        struct intel_connector *connector =
                to_intel_connector(old_conn_state->connector);
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        bool last_mst_stream;
+       u32 val;
  
        intel_dp->active_mst_links--;
        last_mst_stream = intel_dp->active_mst_links == 0;
+       WARN_ON(INTEL_GEN(dev_priv) >= 12 && last_mst_stream &&
+               !intel_dp_mst_is_master_trans(old_crtc_state));
  
        intel_crtc_vblank_off(old_crtc_state);
  
        intel_disable_pipe(old_crtc_state);
  
+       drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+       val = I915_READ(TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder));
+       val &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
+       I915_WRITE(TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder), val);
+       if (intel_de_wait_for_set(dev_priv, intel_dp->regs.dp_tp_status,
+                                 DP_TP_STATUS_ACT_SENT, 1))
+               DRM_ERROR("Timed out waiting for ACT sent when disabling\n");
+       drm_dp_check_act_status(&intel_dp->mst_mgr);
+       drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
        intel_ddi_disable_transcoder_func(old_crtc_state);
  
        if (INTEL_GEN(dev_priv) >= 9)
-               skylake_scaler_disable(old_crtc_state);
+               skl_scaler_disable(old_crtc_state);
        else
-               ironlake_pfit_disable(old_crtc_state);
+               ilk_pfit_disable(old_crtc_state);
  
        /*
+        * Power down mst path before disabling the port, otherwise we end
+        * up getting interrupts from the sink upon detecting link loss.
+        */
+       drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
+                                    false);
+       /*
         * From TGL spec: "If multi-stream slave transcoder: Configure
         * Transcoder Clock Select to direct no clock to the transcoder"
         *
        if (INTEL_GEN(dev_priv) < 12 || !last_mst_stream)
                intel_ddi_disable_pipe_clock(old_crtc_state);
  
-       /* this can fail */
-       drm_dp_check_act_status(&intel_dp->mst_mgr);
-       /* and this can also fail */
-       drm_dp_update_payload_part2(&intel_dp->mst_mgr);
-       drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
-       /*
-        * Power down mst path before disabling the port, otherwise we end
-        * up getting interrupts from the sink upon detecting link loss.
-        */
-       drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
-                                    false);
  
        intel_mst->connector = NULL;
        if (last_mst_stream)
@@@ -289,7 -407,7 +408,7 @@@ static void intel_mst_pre_pll_enable_dp
                                        const struct intel_crtc_state *pipe_config,
                                        const struct drm_connector_state *conn_state)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
  
@@@ -302,7 -420,7 +421,7 @@@ static void intel_mst_pre_enable_dp(str
                                    const struct intel_crtc_state *pipe_config,
                                    const struct drm_connector_state *conn_state)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        connector->encoder = encoder;
        intel_mst->connector = connector;
        first_mst_stream = intel_dp->active_mst_links == 0;
+       WARN_ON(INTEL_GEN(dev_priv) >= 12 && first_mst_stream &&
+               !intel_dp_mst_is_master_trans(pipe_config));
  
        DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links);
  
@@@ -360,7 -480,7 +481,7 @@@ static void intel_mst_enable_dp(struct 
                                const struct intel_crtc_state *pipe_config,
                                const struct drm_connector_state *conn_state)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
  static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
                                      enum pipe *pipe)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        *pipe = intel_mst->pipe;
        if (intel_mst->connector)
                return true;
  static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
                                        struct intel_crtc_state *pipe_config)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
  
        intel_ddi_get_config(&intel_dig_port->base, pipe_config);
@@@ -499,7 -619,7 +620,7 @@@ static const struct drm_connector_helpe
  
  static void intel_dp_mst_encoder_destroy(struct drm_encoder *encoder)
  {
-       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
+       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(to_intel_encoder(encoder));
  
        drm_encoder_cleanup(encoder);
        kfree(intel_mst);
@@@ -723,3 -843,14 +844,14 @@@ intel_dp_mst_encoder_cleanup(struct int
        drm_dp_mst_topology_mgr_destroy(&intel_dp->mst_mgr);
        /* encoders will get killed by normal cleanup */
  }
+ bool intel_dp_mst_is_master_trans(const struct intel_crtc_state *crtc_state)
+ {
+       return crtc_state->mst_master_transcoder == crtc_state->cpu_transcoder;
+ }
+ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state)
+ {
+       return crtc_state->mst_master_transcoder != INVALID_TRANSCODER &&
+              crtc_state->mst_master_transcoder != crtc_state->cpu_transcoder;
+ }