[PATCH 43/44] drm/i915/hdmi: Compute output format for HDMI FRL mode

Ankit Nautiyal <[email protected]>
Newsgroups org.freedesktop.lists.intel-xe,org.freedesktop.lists.dri-devel,org.freedesktop.lists.intel-gfx
Message-ID <[email protected]>
If the source and sink support FRL, then compute output format
that can support HDMI FRL mode. This in turn calculates the FRL
configuration, clocks etc required to support a video mode with
FRL transmission.

Signed-off-by: Ankit Nautiyal <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 66 +++++++++++++++++------
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 05d3bb40ca30..1773b2096e9f 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2467,10 +2467,11 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
 	return intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits, enable_frl);
 }
 
-static int intel_hdmi_compute_formats(struct intel_encoder *encoder,
-				      struct intel_crtc_state *crtc_state,
-				      const struct drm_connector_state *conn_state,
-				      bool respect_downstream_limits)
+static int _intel_hdmi_compute_formats(struct intel_encoder *encoder,
+				       struct intel_crtc_state *crtc_state,
+				       const struct drm_connector_state *conn_state,
+				       bool respect_downstream_limits,
+				       bool enable_frl)
 {
 	struct intel_display *display = to_intel_display(encoder);
 	struct intel_connector *connector = to_intel_connector(conn_state->connector);
@@ -2482,7 +2483,7 @@ static int intel_hdmi_compute_formats(struct intel_encoder *encoder,
 		ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
 						       respect_downstream_limits,
 						       INTEL_OUTPUT_FORMAT_YCBCR420,
-						       false);
+						       enable_frl);
 
 		if (ret && !respect_downstream_limits) {
 			drm_dbg_kms(display->drm,
@@ -2491,19 +2492,19 @@ static int intel_hdmi_compute_formats(struct intel_encoder *encoder,
 			ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
 							       respect_downstream_limits,
 							       INTEL_OUTPUT_FORMAT_RGB,
-							       false);
+							       enable_frl);
 		}
 	} else {
 		ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
 						       respect_downstream_limits,
 						       INTEL_OUTPUT_FORMAT_RGB,
-						       false);
+						       enable_frl);
 
 		if (ret && drm_mode_is_420_also(info, adjusted_mode))
 			ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
 							       respect_downstream_limits,
 							       INTEL_OUTPUT_FORMAT_YCBCR420,
-							       false);
+							       enable_frl);
 	}
 
 	return ret;
@@ -2544,6 +2545,26 @@ bool intel_hdmi_compute_has_hdmi_sink(struct intel_encoder *encoder,
 		!intel_hdmi_is_cloned(crtc_state);
 }
 
+static int intel_hdmi_compute_formats(struct intel_encoder *encoder,
+				      struct intel_crtc_state *crtc_state,
+				      const struct drm_connector_state *conn_state,
+				      bool enable_frl)
+{
+	int ret;
+
+	/*
+	 * Try to respect downstream TMDS clock limits first, if
+	 * that fails assume the user might know something we don't.
+	 */
+	ret = _intel_hdmi_compute_formats(encoder, crtc_state,
+					  conn_state, true, enable_frl);
+	if (ret)
+		ret = _intel_hdmi_compute_formats(encoder, crtc_state,
+						  conn_state, false, enable_frl);
+
+	return ret;
+}
+
 int intel_hdmi_compute_config(struct intel_encoder *encoder,
 			      struct intel_crtc_state *pipe_config,
 			      struct drm_connector_state *conn_state)
@@ -2552,6 +2573,9 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
 	struct intel_connector *connector = to_intel_connector(conn_state->connector);
 	struct drm_scdc *scdc = &connector->base.display_info.hdmi.scdc;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	bool enable_frl = false;
+	int lane_count = 4;
 	int ret;
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -2576,13 +2600,23 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 		intel_hdmi_has_audio(encoder, pipe_config, conn_state) &&
 		intel_audio_compute_config(encoder, pipe_config, conn_state);
 
-	/*
-	 * Try to respect downstream TMDS clock limits first, if
-	 * that fails assume the user might know something we don't.
-	 */
-	ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, true);
-	if (ret)
-		ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, false);
+	if (HAS_HDMI_FRL(display) &&
+	    intel_bios_hdmi_max_frl_rate(encoder) &&
+	    intel_hdmi->has_sink_hdmi_21)
+		enable_frl = true;
+
+	ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, false);
+
+	if (ret && enable_frl) {
+		ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, true);
+		drm_dbg_kms(display->drm,
+			    "Enabling FRL mode with lanes = %d rate = %d\n",
+			    pipe_config->frl.required_lanes,
+			    pipe_config->frl.required_rate);
+		pipe_config->frl.enable = true;
+		lane_count = pipe_config->frl.required_lanes;
+	}
+
 	if (ret) {
 		drm_dbg_kms(display->drm,
 			    "unsupported HDMI clock (%d kHz), rejecting mode\n",
@@ -2601,7 +2635,7 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 		adjusted_mode->picture_aspect_ratio =
 			conn_state->picture_aspect_ratio;
 
-	pipe_config->lane_count = 4;
+	pipe_config->lane_count = lane_count;
 
 	if (scdc->scrambling.supported && source_supports_scrambling(encoder) &&
 	    !pipe_config->frl.enable) {
-- 
2.50.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.