diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 818f3a3..e8ddba0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15799,3 +15799,166 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
 		spin_unlock_irq(&dev->event_lock);
 	}
 }
+
+static bool
+intel_upfront_link_train_config(struct drm_device *dev,
+				struct intel_dp *intel_dp,
+				struct intel_crtc *crtc,
+				uint8_t link_bw,
+				uint8_t lane_count)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_connector *connector = intel_dp->attached_connector;
+	struct intel_encoder *encoder = connector->encoder;
+	bool success;
+
+	intel_dp->link_bw = link_bw;
+	intel_dp->lane_count = lane_count;
+
+	/* Find port clock from link_bw */
+	crtc->config->port_clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+
+	/* Enable PLL followed by port */
+	if (IS_BROADWELL(dev)) {
+		hsw_dp_set_ddi_pll_sel(crtc->config, intel_dp->link_bw);
+		if (intel_crtc_to_shared_dpll(crtc))
+			intel_enable_shared_dpll(crtc);
+
+		intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
+
+	} else if (IS_CHERRYVIEW(dev)) {
+		intel_dp_set_clock(encoder, crtc->config, intel_dp->link_bw);
+		if (encoder->pre_pll_enable)
+			encoder->pre_pll_enable(encoder);
+		if (!intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI))
+			chv_enable_pll(crtc, crtc->config);
+	}
+	if (encoder->pre_enable)
+		encoder->pre_enable(encoder);
+
+	success = intel_dp->train_set_valid;
+
+	/* Reset encoder for next retry or for clean up */
+	if (encoder->post_disable)
+		encoder->post_disable(encoder);
+	if (IS_CHERRYVIEW(dev)) {
+		if (!intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI))
+			chv_disable_pll(dev_priv, crtc->pipe);
+	} else if (IS_BROADWELL(dev)) {
+		intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
+		if (intel_crtc_to_shared_dpll(crtc))
+			intel_disable_shared_dpll(crtc);
+	}
+
+	intel_dp->train_set_valid = false;
+
+	return success;
+}
+
+bool
+intel_upfront_link_train(struct drm_device *dev,
+			 struct intel_dp *intel_dp,
+			 struct intel_crtc *crtc)
+{
+	struct intel_connector *connector = intel_dp->attached_connector;
+	struct intel_encoder *encoder = connector->encoder;
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);
+	uint8_t link_bw, lane_count;
+	bool found = false;
+	bool valid_crtc = !!crtc;
+
+	if (!connector || !encoder) {
+		DRM_DEBUG_KMS("dp connector/encoder is NULL\n");
+		return false;
+	}
+
+	/* Find an unused crtc and use it for link training if no crtc is given */
+	if (!crtc) {
+		for_each_intel_crtc(dev, crtc) {
+			if (intel_crtc_active(&crtc->base))
+				continue;
+
+			/* Make sure the new crtc will work with the encoder */
+			if (!drm_encoder_crtc_ok(&encoder->base, &crtc->base))
+				continue;
+
+			encoder->base.crtc = &crtc->base;
+
+			found = true;
+			break;
+		}
+
+		if (!found) {
+			DRM_ERROR("Could not find crtc for upfront link training\n");
+			goto exit;
+		}
+	}
+
+	DRM_DEBUG_KMS("upfront link training on pipe:%c\n",
+		      pipe_name(crtc->pipe));
+
+	/* check the reversed state of the adapter first */
+
+	/* unset the reversal bit */
+	intel_dig_port->saved_port_bits &= ~DDI_BUF_PORT_REVERSAL;
+
+	/* Initialize with Max Link rate supported by panel & one lane */
+	intel_dp->link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
+	intel_dp->lane_count = 1;
+
+	/* Check if link training passed; if not, update the reversed state */
+	if (!intel_upfront_link_train_config(dev, intel_dp, crtc,
+					intel_dp->dpcd[DP_MAX_LINK_RATE], 1))
+		intel_dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL;
+
+	found = false;
+
+	/* Initialize with Max Link rate & lane count supported by panel */
+	link_bw =  intel_dp->dpcd[DP_MAX_LINK_RATE];
+	lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
+
+	do {
+		/* Check if link training passed; if so update lane count */
+		if (intel_upfront_link_train_config(dev, intel_dp, crtc,
+					link_bw, lane_count)) {
+			intel_dp->dpcd[DP_MAX_LANE_COUNT] &=
+						~DP_MAX_LANE_COUNT_MASK;
+			intel_dp->dpcd[DP_MAX_LANE_COUNT] |=
+				intel_dp->lane_count & DP_MAX_LANE_COUNT_MASK;
+
+			found = true;
+			goto exit;
+		}
+
+		DRM_DEBUG_KMS("upfront link training failed. lanes:%d bw:%d\n",
+				intel_dp->lane_count, intel_dp->link_bw);
+
+		/* Go down to the next level and retry link training */
+		if (lane_count == 4) {
+			lane_count = 2;
+		} else if (lane_count == 2) {
+			lane_count = 1;
+		} else if (link_bw == DP_LINK_BW_5_4) {
+			link_bw = DP_LINK_BW_2_7;
+			lane_count = 4;
+		} else if (link_bw == DP_LINK_BW_2_7) {
+			link_bw = DP_LINK_BW_1_62;
+			lane_count = 4;
+		} else {
+			/* Tried all combinations, so exit */
+			break;
+		}
+
+	} while (1);
+
+exit:
+	/* Clear local associations made */
+	if (!valid_crtc)
+		encoder->base.crtc = NULL;
+
+	if (found)
+		DRM_DEBUG_KMS("upfront link training passed. lanes:%d bw:%d\n",
+				intel_dp->lane_count, intel_dp->link_bw);
+
+	return found;
+}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 44f8a32..187800b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1144,7 +1144,7 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
 	pipe_config->dpll_hw_state.ctrl1 = ctrl1;
 }
 
-static void
+void
 hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config, int link_bw)
 {
 	memset(&pipe_config->dpll_hw_state, 0,
@@ -1202,7 +1202,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
 		return (DP_LINK_BW_2_7 >> 3) + 1;
 }
 
-static void
+void
 intel_dp_set_clock(struct intel_encoder *encoder,
 		   struct intel_crtc_state *pipe_config, int link_bw)
 {
@@ -4423,6 +4423,10 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 	else if (ret == 0)
 		return connector_status_disconnected;
 
+	/* Avoid DPCD opertations if status is same */
+	if (intel_dp->attached_connector->base.status == connector_status_connected)
+		return connector_status_connected;
+
 	return intel_dp_detect_dpcd(intel_dp);
 }
 
@@ -4495,7 +4499,9 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
 	struct drm_device *dev = connector->dev;
+	struct intel_crtc *intel_crtc;
 	enum drm_connector_status status;
 	enum intel_display_power_domain power_domain;
 	bool ret;
@@ -4540,6 +4546,18 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+
+	if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT &&
+	    (IS_BROADWELL(dev) || IS_CHERRYVIEW(dev))) {
+		/* Do not handle connected boot scenario where panel is enabled
+		 * by GOP/VBIOS.
+		 */
+		if ((connector->status != connector_status_connected) &&
+		    !(intel_encoder->connectors_active &&
+		      crtc && crtc->enabled))
+			intel_upfront_link_train(dev, intel_dp, NULL);
+	}
+
 	status = connector_status_connected;
 
 	/* Try to read the source of the interrupt */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 320c9e6..fcc95d5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1163,6 +1163,13 @@ bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 void intel_dp_start_link_train(struct intel_dp *intel_dp);
 void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 void intel_dp_stop_link_train(struct intel_dp *intel_dp);
+bool intel_upfront_link_train(struct drm_device *dev,
+			      struct intel_dp *intel_dp,
+			      struct intel_crtc *crtc);
+void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config, int link_bw);
+void intel_dp_set_clock(struct intel_encoder *encoder,
+			struct intel_crtc_state *pipe_config, int link_bw);
+
 void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc);
