Re: [PATCH v3 15/17] drm/i915: Allow M/N change during fastset on bdw+

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Intel-gfx <intel-gfx-bounces@xxxxxxxxxxxxxxxxxxxxx> On Behalf Of Ville
> Syrjala
> Sent: Monday, June 20, 2022 8:52 PM
> To: intel-gfx@xxxxxxxxxxxxxxxxxxxxx
> Subject:  [PATCH v3 15/17] drm/i915: Allow M/N change during
> fastset on bdw+
> 
> From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
> 
> On BDW+ M/N are double buffered and so we can easily reprogram them during
> a fastset. So for eDP panels that support seamless DRRS we can just change
> these without a full modeset.
> 
> For earlier platforms we'd need to play tricks with M1/N1 vs.
> M2/N2 during the fastset to make sure we do the switch atomically.
> Not sure the added complexity is worth the hassle, so leave it alone for now.
> 
> The slight downside is that we have to keep the link running at a link rate
> capable of supporting the highest refresh rate we want to use. For the moment
> we just pick the highest mode the panel reports and calculate the link based on
> that. This might need further refinement (eg. if we run into bandwidth
> restrictions)...
> 
> v2: Only use the high link rate if the platform really supports
>     the seamless M/N change uring fastset (ie. bdw+)
> v3: Rebase due to HAS_DOUBLE_BUFFERED_M_N()
> 

Reviewed-by: Mika Kahola <mika.kahola@xxxxxxxxx>

> Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  | 13 +++++--
>  .../drm/i915/display/intel_display_types.h    |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c       | 37 ++++++++++++++++---
>  3 files changed, 43 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index afef6a826ef2..43c00f8b4057 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -5719,7 +5719,8 @@ intel_pipe_config_compare(const struct
> intel_crtc_state *current_config,
>  	PIPE_CONF_CHECK_X(lane_lat_optim_mask);
> 
>  	if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) {
> -		PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
> +		if (!fastset || !pipe_config->seamless_m_n)
> +			PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
>  	} else {
>  		PIPE_CONF_CHECK_M_N(dp_m_n);
>  		PIPE_CONF_CHECK_M_N(dp_m2_n2);
> @@ -5851,8 +5852,10 @@ intel_pipe_config_compare(const struct
> intel_crtc_state *current_config,
>  	if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5)
>  		PIPE_CONF_CHECK_I(pipe_bpp);
> 
> -	PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_clock);
> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_clock);
> +	if (!fastset || !pipe_config->seamless_m_n) {
> +		PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_clock);
> +		PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_clock);
> +	}
>  	PIPE_CONF_CHECK_I(port_clock);
> 
>  	PIPE_CONF_CHECK_I(min_voltage_level);
> @@ -6991,6 +6994,10 @@ static void intel_pipe_fastset(const struct
> intel_crtc_state *old_crtc_state,
>  	if (DISPLAY_VER(dev_priv) >= 9 ||
>  	    IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
>  		hsw_set_linetime_wm(new_crtc_state);
> +
> +	if (new_crtc_state->seamless_m_n)
> +		intel_cpu_transcoder_set_m1_n1(crtc, new_crtc_state-
> >cpu_transcoder,
> +					       &new_crtc_state->dp_m_n);
>  }
> 
>  static void commit_pipe_pre_planes(struct intel_atomic_state *state, diff --git
> a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 8b0949b6dc75..95159d1c8ca8 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1129,6 +1129,7 @@ struct intel_crtc_state {
>  	/* m2_n2 for eDP downclock */
>  	struct intel_link_m_n dp_m2_n2;
>  	bool has_drrs;
> +	bool seamless_m_n;
> 
>  	/* PSR is supported but might not be enabled due the lack of enabled
> planes */
>  	bool has_psr;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index cf7e4e105891..90fa8eda6911 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1311,21 +1311,45 @@ intel_dp_adjust_compliance_config(struct intel_dp
> *intel_dp,
>  	}
>  }
> 
> +static bool has_seamless_m_n(struct intel_connector *connector) {
> +	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> +
> +	/*
> +	 * Seamless M/N reprogramming only implemented
> +	 * for BDW+ double buffered M/N registers so far.
> +	 */
> +	return HAS_DOUBLE_BUFFERED_M_N(i915) &&
> +		intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; }
> +
> +static int intel_dp_mode_clock(const struct intel_crtc_state *crtc_state,
> +			       const struct drm_connector_state *conn_state) {
> +	struct intel_connector *connector = to_intel_connector(conn_state-
> >connector);
> +	const struct drm_display_mode *adjusted_mode =
> +&crtc_state->hw.adjusted_mode;
> +
> +	/* FIXME a bit of a mess wrt clock vs. crtc_clock */
> +	if (has_seamless_m_n(connector))
> +		return intel_panel_highest_mode(connector, adjusted_mode)-
> >clock;
> +	else
> +		return adjusted_mode->crtc_clock;
> +}
> +
>  /* Optimize link config in order: max bpp, min clock, min lanes */  static int
> intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
>  				  struct intel_crtc_state *pipe_config,
> +				  const struct drm_connector_state
> *conn_state,
>  				  const struct link_config_limits *limits)  {
> -	struct drm_display_mode *adjusted_mode = &pipe_config-
> >hw.adjusted_mode;
> -	int bpp, i, lane_count;
> +	int bpp, i, lane_count, clock = intel_dp_mode_clock(pipe_config,
> +conn_state);
>  	int mode_rate, link_rate, link_avail;
> 
>  	for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
>  		int output_bpp = intel_dp_output_bpp(pipe_config-
> >output_format, bpp);
> 
> -		mode_rate = intel_dp_link_required(adjusted_mode-
> >crtc_clock,
> -						   output_bpp);
> +		mode_rate = intel_dp_link_required(clock, output_bpp);
> 
>  		for (i = 0; i < intel_dp->num_common_rates; i++) {
>  			link_rate = intel_dp_common_rate(intel_dp, i); @@ -
> 1625,7 +1649,7 @@ intel_dp_compute_link_config(struct intel_encoder
> *encoder,
>  	 * Optimize for slow and wide for everything, because there are some
>  	 * eDP 1.3 and 1.4 panels don't work well with fast and narrow.
>  	 */
> -	ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config,
> &limits);
> +	ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config,
> +conn_state, &limits);
> 
>  	if (ret || joiner_needs_dsc || intel_dp->force_dsc_en) {
>  		drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s,
> force=%s)\n", @@ -1913,6 +1937,9 @@ intel_dp_drrs_compute_config(struct
> intel_connector *connector,
>  		intel_panel_downclock_mode(connector, &pipe_config-
> >hw.adjusted_mode);
>  	int pixel_clock;
> 
> +	if (has_seamless_m_n(connector))
> +		pipe_config->seamless_m_n = true;
> +
>  	if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
>  		if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config-
> >cpu_transcoder))
>  			intel_zero_m_n(&pipe_config->dp_m2_n2);
> --
> 2.35.1





[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux