diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index 05185db6635e..8c5dfbb98811 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -219,6 +219,35 @@ static const struct drm_prop_enum_list force_audio_names[] = {
 	{ HDMI_AUDIO_ON, "on" },
 };
 
+int intel_connector_apply_border(struct intel_crtc_state *crtc_state,
+				 void *border_data)
+{
+	const struct drm_display_mode *adjusted_mode =
+		&crtc_state->hw.adjusted_mode;
+	int width = adjusted_mode->crtc_hdisplay;
+	int height = adjusted_mode->crtc_vdisplay;
+	struct drm_rect *border = border_data;
+	int left = border->x1;
+	int top = border->y1;
+	int right = border->x2;
+	int bottom = border->y2;
+
+	if (left < 0 || top < 0 || right < 0 || bottom < 0)
+		return -EINVAL;
+
+	if (left + right >= width || top + bottom >= height)
+		return -EINVAL;
+
+	width -= (left + right);
+	height -= (top + bottom);
+
+	drm_rect_init(&crtc_state->border.dst,
+		      left, top, width, height);
+	crtc_state->border.enabled = true;
+
+	return 0;
+}
+
 void
 intel_attach_force_audio_property(struct drm_connector *connector)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h
index ab88b57d475b..93106d855452 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -26,6 +26,8 @@ bool intel_connector_get_hw_state(struct intel_connector *connector);
 enum pipe intel_connector_get_pipe(struct intel_connector *connector);
 int intel_connector_update_modes(struct drm_connector *connector,
 				 const struct drm_edid *drm_edid);
+int intel_connector_apply_border(struct intel_crtc_state *crtc_state,
+				 void *border_data);
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *ddc);
 void intel_attach_force_audio_property(struct drm_connector *connector);
 void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 0ea62c278948..af615e576fe7 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1679,9 +1679,12 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
 		glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true);
 
 	if (DISPLAY_VER(dev_priv) >= 9) {
-		const struct drm_rect *dst = &new_crtc_state->pch_pfit.dst;
+		const struct drm_rect *dst = new_crtc_state->pch_pfit.enabled ?
+					     &new_crtc_state->pch_pfit.dst :
+					     &new_crtc_state->border.dst;
 
-		if (new_crtc_state->pch_pfit.enabled)
+		if (new_crtc_state->pch_pfit.enabled ||
+		    new_crtc_state->border.enabled)
 			skl_program_crtc_scaler(new_crtc_state, dst);
 	} else {
 		ilk_pfit_enable(new_crtc_state);
@@ -5196,6 +5199,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 		PIPE_CONF_CHECK_BOOL(pch_pfit.enabled);
 		PIPE_CONF_CHECK_RECT(pch_pfit.dst);
 
+		PIPE_CONF_CHECK_BOOL(border.enabled);
+		PIPE_CONF_CHECK_RECT(border.dst);
+
 		PIPE_CONF_CHECK_I(scaler_state.scaler_id);
 		PIPE_CONF_CHECK_I(pixel_rate);
 
@@ -6564,9 +6570,12 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
 
 	/* on skylake this is done by detaching scalers */
 	if (DISPLAY_VER(dev_priv) >= 9) {
-		const struct drm_rect *dst = &new_crtc_state->pch_pfit.dst;
+		const struct drm_rect *dst = new_crtc_state->pch_pfit.enabled ?
+					     &new_crtc_state->pch_pfit.dst :
+					     &new_crtc_state->border.dst;
 
-		if (new_crtc_state->pch_pfit.enabled)
+		if (new_crtc_state->pch_pfit.enabled ||
+		    new_crtc_state->border.enabled)
 			skl_program_crtc_scaler(new_crtc_state, dst);
 	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		if (new_crtc_state->pch_pfit.enabled)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 399ed0867c20..6e46e585a0da 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1419,6 +1419,11 @@ struct intel_crtc_state {
 		u8 pixel_overlap;
 	} splitter;
 
+	struct {
+		struct drm_rect dst;
+		bool enabled;
+	} border;
+
 	/* for loading single buffered registers during vblank */
 	struct drm_vblank_work vblank_work;
 };
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 065e685ada84..0f552537d42c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2842,6 +2842,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 			struct intel_crtc_state *pipe_config,
 			struct drm_connector_state *conn_state)
 {
+	const struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -2889,6 +2891,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 			return ret;
 	}
 
+	if (intel_conn_state->border) {
+		ret = intel_connector_apply_border(pipe_config,
+					intel_conn_state->border->data);
+		if (ret)
+			return ret;
+	}
+
 	pipe_config->limited_color_range =
 		intel_dp_limited_color_range(pipe_config, conn_state);
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index ac736d708c22..7428ff5d658a 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2285,6 +2285,8 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 			      struct intel_crtc_state *pipe_config,
 			      struct drm_connector_state *conn_state)
 {
+	const struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
 	struct drm_connector *connector = conn_state->connector;
@@ -2330,6 +2332,13 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 			return ret;
 	}
 
+	if (intel_conn_state->border) {
+		ret = intel_connector_apply_border(pipe_config,
+					intel_conn_state->border->data);
+		if (ret)
+			return ret;
+	}
+
 	pipe_config->limited_color_range =
 		intel_hdmi_limited_color_range(pipe_config, conn_state);
 
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index 67a87cc0411a..a0a26e0b4e98 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -237,11 +237,16 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
 {
 	const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
+	bool need_scaler = crtc_state->pch_pfit.enabled ||
+			   crtc_state->border.enabled;
 	int width, height;
 
 	if (crtc_state->pch_pfit.enabled) {
 		width = drm_rect_width(&crtc_state->pch_pfit.dst);
 		height = drm_rect_height(&crtc_state->pch_pfit.dst);
+	} else if (crtc_state->border.enabled) {
+		width = drm_rect_width(&crtc_state->border.dst);
+		height = drm_rect_height(&crtc_state->border.dst);
 	} else {
 		width = pipe_mode->crtc_hdisplay;
 		height = pipe_mode->crtc_vdisplay;
@@ -251,8 +256,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
 				 &crtc_state->scaler_state.scaler_id,
 				 drm_rect_width(&crtc_state->pipe_src),
 				 drm_rect_height(&crtc_state->pipe_src),
-				 width, height, NULL, 0,
-				 crtc_state->pch_pfit.enabled);
+				 width, height, NULL, 0, need_scaler);
 }
 
 /**
@@ -859,6 +863,7 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state)
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+	struct drm_rect *dst;
 	int id = -1;
 	int i;
 
@@ -871,12 +876,19 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state)
 			continue;
 
 		id = i;
-		crtc_state->pch_pfit.enabled = true;
 
 		pos = intel_de_read(dev_priv, SKL_PS_WIN_POS(crtc->pipe, i));
 		size = intel_de_read(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, i));
 
-		drm_rect_init(&crtc_state->pch_pfit.dst,
+		if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+			crtc_state->pch_pfit.enabled = true;
+			dst = &crtc_state->pch_pfit.dst;
+		} else {
+			crtc_state->border.enabled = true;
+			dst = &crtc_state->border.dst;
+		}
+
+		drm_rect_init(dst,
 			      REG_FIELD_GET(PS_WIN_XPOS_MASK, pos),
 			      REG_FIELD_GET(PS_WIN_YPOS_MASK, pos),
 			      REG_FIELD_GET(PS_WIN_XSIZE_MASK, size),
