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