diff mbox

[2/3] drm/i915: extract intel_dp_compute_link_config

Message ID 1398374579-5697-2-git-send-email-przanoni@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paulo Zanoni April 24, 2014, 9:22 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Extract this function to make the input and output parameters more
clear to the code reader.

I also have plans to allow ways to change the current parameters, so
the code will get even more complicated without the refactor. I also
have plans to add alternative implementations to
intel_dp_compute_link_config() and, again, the refactor makes it
easier.

Another change worth noticing is that now we will print all our
"attempts" in dmesg (see the debug code at link_config_is_possible()).
This will allow us to quickly identify if the user is trying fast and
narrow, or wide and slow, and also identify the minimum and maximum BW
and lane count values used by the code.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 94 +++++++++++++++++++++++++++--------------
 1 file changed, 63 insertions(+), 31 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 19537a6..884166b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -768,6 +768,52 @@  intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
 	I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
 }
 
+static bool link_config_is_possible(int mode_rate, int lanes, int bw)
+{
+	int link_clock, link_avail;
+
+	link_clock = drm_dp_bw_code_to_link_rate(bw);
+	link_avail = intel_dp_max_data_rate(link_clock, lanes);
+
+	DRM_DEBUG_KMS("DP link avail with 0x%x bw and %d lanes: %d. Required: %d (%d%%)\n",
+		      bw, lanes, link_avail, mode_rate,
+		      mode_rate * 100 / link_avail);
+
+	return (mode_rate <= link_avail);
+}
+
+/*
+ * This function tries to find the minimal number of lanes and BW required based
+ * on the parameters given. If not possible, it returns false.
+ */
+static bool intel_dp_compute_link_config(int mode_clock, int bpp,
+					 int min_lanes, int max_lanes,
+					 int min_bw, int max_bw,
+					 int *lanes_used, int *bw_used)
+{
+	/* Conveniently, the link BW constants become indices with a shift...*/
+	static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 };
+	int min_bw_index = min_bw >> 3;
+	int max_bw_index = max_bw >> 3;
+	int mode_rate;
+	int lanes, bw_it;
+
+	mode_rate = intel_dp_link_required(mode_clock, bpp);
+
+	for (lanes = min_lanes; lanes <= max_lanes; lanes <<= 1)
+		for (bw_it = min_bw_index; bw_it <= max_bw_index; bw_it++)
+			if (link_config_is_possible(mode_rate, lanes,
+						    bws[bw_it]))
+				goto found;
+
+	return false;
+
+found:
+	*lanes_used = lanes;
+	*bw_used = bws[bw_it];
+	return true;
+}
+
 bool
 intel_dp_compute_config(struct intel_encoder *encoder,
 			struct intel_crtc_config *pipe_config)
@@ -779,13 +825,10 @@  intel_dp_compute_config(struct intel_encoder *encoder,
 	enum port port = dp_to_dig_port(intel_dp)->port;
 	struct intel_crtc *intel_crtc = encoder->new_crtc;
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
-	int lane_count, clock;
+	int lanes_used, bw_used;
 	int max_lane_count = intel_dp_max_lane_count(intel_dp);
-	/* Conveniently, the link BW constants become indices with a shift...*/
-	int max_clock = intel_dp_max_link_bw(intel_dp) >> 3;
-	int bpp, mode_rate;
-	static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 };
-	int link_avail, link_clock;
+	int max_bw = intel_dp_max_link_bw(intel_dp);
+	int bpp;
 
 	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A)
 		pipe_config->has_pch_encoder = true;
@@ -808,7 +851,7 @@  intel_dp_compute_config(struct intel_encoder *encoder,
 
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
 		      "max bw %02x pixel clock %iKHz\n",
-		      max_lane_count, bws[max_clock],
+		      max_lane_count, max_bw,
 		      adjusted_mode->crtc_clock);
 
 	/* Walk through all bpp values. Luckily they're all nicely spaced with 2
@@ -821,26 +864,17 @@  intel_dp_compute_config(struct intel_encoder *encoder,
 		bpp = dev_priv->vbt.edp_bpp;
 	}
 
-	for (; bpp >= 6*3; bpp -= 2*3) {
-		mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
-						   bpp);
-
-		for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
-			for (clock = 0; clock <= max_clock; clock++) {
-				link_clock = drm_dp_bw_code_to_link_rate(bws[clock]);
-				link_avail = intel_dp_max_data_rate(link_clock,
-								    lane_count);
-
-				if (mode_rate <= link_avail) {
-					goto found;
-				}
-			}
-		}
-	}
+	for (; bpp >= 6*3; bpp -= 2*3)
+		if (intel_dp_compute_link_config(adjusted_mode->crtc_clock, bpp,
+						 1, max_lane_count,
+						 DP_LINK_BW_1_62,
+						 max_bw,
+						 &lanes_used, &bw_used))
+			break;
 
-	return false;
+	if (bpp < 6*3)
+		return false;
 
-found:
 	if (intel_dp->color_range_auto) {
 		/*
 		 * See:
@@ -856,25 +890,23 @@  found:
 	if (intel_dp->color_range)
 		pipe_config->limited_color_range = true;
 
-	intel_dp->link_bw = bws[clock];
-	intel_dp->lane_count = lane_count;
+	intel_dp->link_bw = bw_used;
+	intel_dp->lane_count = lanes_used;
 	pipe_config->pipe_bpp = bpp;
 	pipe_config->port_clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
 
 	DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
 		      intel_dp->link_bw, intel_dp->lane_count,
 		      pipe_config->port_clock, bpp);
-	DRM_DEBUG_KMS("DP link bw required %i available %i\n",
-		      mode_rate, link_avail);
 
-	intel_link_compute_m_n(bpp, lane_count,
+	intel_link_compute_m_n(bpp, lanes_used,
 			       adjusted_mode->crtc_clock,
 			       pipe_config->port_clock,
 			       &pipe_config->dp_m_n);
 
 	if (intel_connector->panel.downclock_mode != NULL &&
 		intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
-			intel_link_compute_m_n(bpp, lane_count,
+			intel_link_compute_m_n(bpp, lanes_used,
 				intel_connector->panel.downclock_mode->clock,
 				pipe_config->port_clock,
 				&pipe_config->dp_m2_n2);