[Intel-gfx] [PATCH v2 2/3] drm/i915/display/dp: Try to fallback to previous link config if modeset is not allowed

José Roberto de Souza jose.souza at intel.com
Mon May 2 20:41:16 UTC 2022


When an atomic commit has changes that allows it to go to a lower DP
link configuration it will require a modeset but userspace might not
want it, so it would not set the modeset allowed flag causing
commit to fail.

Here in such case it tries to keep previous and trained link
configuration for the new state.

Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 86 ++++++++++++++++++++++++-
 1 file changed, 85 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index e4a79c11fd255..cc9be82e128f4 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1596,6 +1596,16 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 			return ret;
 	}
 
+	return 0;
+}
+
+static void
+intel_dp_print_link_config(struct intel_crtc_state *pipe_config)
+{
+	struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev);
+	const struct drm_display_mode *adjusted_mode =
+			&pipe_config->hw.adjusted_mode;
+
 	if (pipe_config->dsc.compression_enable) {
 		drm_dbg_kms(&i915->drm,
 			    "DP lane count %d clock %d Input bpp %d Compressed bpp %d\n",
@@ -1621,7 +1631,6 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 			    intel_dp_max_data_rate(pipe_config->port_clock,
 						   pipe_config->lane_count));
 	}
-	return 0;
 }
 
 bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
@@ -1915,6 +1924,72 @@ static bool intel_dp_has_audio(struct intel_encoder *encoder,
 		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
 }
 
+/*
+ * If modeset is not allowed it checks for link computed state and if different
+ * it checks if is possible to fallback to previous configuration.
+ *
+ * Returns 0 if modeset is allowed, link computed states matches or fallback is
+ * possible otherwise returns a errno.
+ */
+static int
+intel_dp_compute_link_config_no_modeset_fallback(struct intel_crtc_state *crtc_state)
+{
+	struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
+	struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+	const struct intel_crtc_state *old_crtc_state;
+	int output_bpp, mode_rate, old_link_avail;
+	struct intel_crtc *crtc;
+
+	if (state->base.allow_modeset)
+		return 0;
+
+	crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
+
+	/* Check if both states matches */
+	if (crtc_state->output_format == old_crtc_state->output_format &&
+	    crtc_state->port_clock == old_crtc_state->port_clock &&
+	    crtc_state->lane_count == old_crtc_state->lane_count &&
+	    crtc_state->pipe_bpp == old_crtc_state->pipe_bpp &&
+	    crtc_state->dsc.compression_enable == old_crtc_state->dsc.compression_enable &&
+	    crtc_state->dsc.compressed_bpp == old_crtc_state->dsc.compressed_bpp &&
+	    crtc_state->dsc.slice_count == old_crtc_state->dsc.slice_count &&
+	    crtc_state->bigjoiner_pipes == old_crtc_state->bigjoiner_pipes)
+		return 0;
+
+	/*
+	 * Modeset will be required if any of this changed, there is no way
+	 * around it
+	 */
+	if (crtc_state->output_format != old_crtc_state->output_format ||
+	    crtc_state->bigjoiner_pipes != old_crtc_state->bigjoiner_pipes ||
+	    crtc_state->dsc.compression_enable != old_crtc_state->dsc.compression_enable)
+		return -EINVAL;
+
+	/* TODO: Not supporting DSC fallback but it might be possible */
+	if (crtc_state->dsc.compression_enable)
+		return -EINVAL;
+
+	output_bpp = intel_dp_output_bpp(crtc_state->output_format,
+					 old_crtc_state->pipe_bpp);
+	mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
+					   output_bpp);
+
+	old_link_avail = intel_dp_max_data_rate(old_crtc_state->port_clock,
+						old_crtc_state->lane_count);
+
+	/* Check if old link configuration has enough bandwidth for new mode */
+	if (mode_rate > old_link_avail)
+		return -EINVAL;
+
+	/* Fallback is possible */
+	crtc_state->lane_count = old_crtc_state->lane_count;
+	crtc_state->pipe_bpp = old_crtc_state->pipe_bpp;
+	crtc_state->port_clock = old_crtc_state->port_clock;
+
+	return 0;
+}
+
 static int
 intel_dp_compute_output_format(struct intel_encoder *encoder,
 			       struct intel_crtc_state *crtc_state,
@@ -1950,8 +2025,17 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
 		crtc_state->output_format = intel_dp_output_format(connector, true);
 		ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
 						   respect_downstream_limits);
+		if (ret)
+			return ret;
 	}
 
+	ret = intel_dp_compute_link_config_no_modeset_fallback(crtc_state);
+	if (ret)
+		drm_dbg_kms(&i915->drm, "DP link configuration requires "
+			    "changes but modeset is not allowed\n");
+
+	intel_dp_print_link_config(crtc_state);
+
 	return ret;
 }
 
-- 
2.36.0



More information about the Intel-gfx mailing list