diff mbox

[6/6] drm/i915/dp: Track available DP MST vcpi time slots

Message ID 20170104092604.jhw4p5cvvblugevq@phenom.ffwll.local (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter Jan. 4, 2017, 9:26 a.m. UTC
On Tue, Jan 03, 2017 at 01:01:51PM -0800, Dhinakaran Pandiyan wrote:
> 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(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ab72858..71e2ac7 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -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;

I don't think the double-loop is needed.

> +
> +		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);
> +			}

Hm, I think it might be useful to have a generic atomic_release function
for connectors in the core atomic helpers. E.g. something like the below:




I think we'll have other connectors in the future where we need to drop
shared resources in a similar fashion.

Cheers, Daniel


> +		}
> +	}
> +
> +	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 {
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 02a1e2c..331909b 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -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)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 6b02dac..ea2e41e 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -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);
>  
> -- 
> 2.7.4
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index b4dfd1e1a4f0..ce55e87b50e5 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -385,8 +385,12 @@  mode_fixup(struct drm_atomic_state *state)
 
 		WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc);
 
-		if (!conn_state->crtc || !conn_state->best_encoder)
+		if (!conn_state->crtc || !conn_state->best_encoder) {
+			if (connector->helper_private->atomic_release)
+				connector->helper_private->atomic_release(connector,
+									  conn_state);
 			continue;
+		}
 
 		crtc_state = drm_atomic_get_existing_crtc_state(state,
 								conn_state->crtc);