@@ -14072,6 +14072,40 @@ static int calc_watermark_data(struct drm_atomic_state *state)
return 0;
}
+static int intel_mst_clear_config(struct drm_atomic_state *state)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+ struct drm_connector *connector;
+ struct drm_connector_state *connector_state;
+ int i, j;
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (!crtc_state->active_changed || crtc_state->active)
+ continue;
+
+ for_each_connector_in_state(state, connector, connector_state, j) {
+ struct intel_encoder *encoder;
+ struct drm_crtc *curr_crtc;
+ int slots;
+
+ encoder = to_intel_encoder(connector->state->best_encoder);
+ if (encoder->type != INTEL_OUTPUT_DP_MST)
+ continue;
+
+ curr_crtc = connector->state->crtc;
+ if (curr_crtc && crtc == curr_crtc) {
+ slots = to_intel_crtc_state(crtc->state)->dp_m_n.tu;
+ return intel_dp_mst_reset_vcpi(encoder,
+ connector_state,
+ slots);
+ }
+ }
+ }
+
+ return 0;
+}
+
/**
* intel_atomic_check - validate state object
* @dev: drm device
@@ -14142,8 +14176,11 @@ static int intel_atomic_check(struct drm_device *dev,
}
if (any_ms) {
- ret = intel_modeset_checks(state);
+ ret = intel_mst_clear_config(state);
+ if (ret)
+ return ret;
+ ret = intel_modeset_checks(state);
if (ret)
return ret;
} else {
@@ -44,6 +44,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
int lane_count, slots;
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int mst_pbn;
+ struct drm_dp_mst_topology_state *topology_state;
pipe_config->has_pch_encoder = false;
bpp = 24;
@@ -65,7 +66,18 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp);
pipe_config->pbn = mst_pbn;
- slots = drm_dp_find_vcpi_slots(&intel_dp->mst_mgr, mst_pbn);
+
+ topology_state = drm_atomic_get_mst_topology_state(state,
+ &intel_dp->mst_mgr);
+ if (topology_state == NULL)
+ return false;
+
+ slots = drm_dp_atomic_find_vcpi_slots(topology_state, connector->port,
+ mst_pbn);
+ if (slots < 0) {
+ DRM_DEBUG_KMS("not enough link bw for this mode\n");
+ return false;
+ }
intel_link_compute_m_n(bpp, lane_count,
adjusted_mode->crtc_clock,
@@ -78,6 +90,28 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
}
+int intel_dp_mst_reset_vcpi(struct intel_encoder *encoder,
+ struct drm_connector_state *conn_state, int slots)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ struct drm_dp_mst_topology_mgr *mgr = &intel_mst->primary->dp.mst_mgr;
+ struct drm_dp_mst_topology_state *topology_state;
+ struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
+ int released;
+
+ topology_state = drm_atomic_get_mst_topology_state(conn_state->state, mgr);
+ if (IS_ERR(topology_state))
+ return PTR_ERR(topology_state);
+
+ released = drm_dp_atomic_release_vcpi_slots(topology_state, connector->port);
+
+ if (WARN_ON(released != slots))
+ return -EINVAL;
+
+ return 0;
+}
+
static void intel_mst_disable_dp(struct intel_encoder *encoder,
struct intel_crtc_state *old_crtc_state,
struct drm_connector_state *old_conn_state)
@@ -1487,6 +1487,9 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
/* intel_dp_mst.c */
int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
+int intel_dp_mst_reset_vcpi(struct intel_encoder *encoder,
+ struct drm_connector_state *conn_state,
+ int slots);
/* intel_dsi.c */
void intel_dsi_init(struct drm_i915_private *dev_priv);
Make use of the added MST helpers to find, allocate and release link bw for atomic modesets. Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com> --- drivers/gpu/drm/i915/intel_display.c | 39 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_dp_mst.c | 36 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 3 +++ 3 files changed, 76 insertions(+), 2 deletions(-)