diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7d6acb4..104a232 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1441,6 +1441,12 @@ struct drm_i915_private {
 	struct drm_property *broadcast_rgb_property;
 	struct drm_property *force_audio_property;
 
+	/*
+	 * Property to dynamically vary the size of the
+	 * PIPESRC or Panel fitter input size
+	 */
+	struct drm_property *input_size_property;
+
 	uint32_t hw_context_size;
 	struct list_head context_list;
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f26be4e..5484ae2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8902,8 +8902,18 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	 * Note that pitch changes could also affect these register.
 	 */
 	if (INTEL_INFO(dev)->gen > 3 &&
-	    (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
-	     fb->pitches[0] != crtc->primary->fb->pitches[0]))
+	    (fb->offsets[0] != crtc->primary->fb->offsets[0]))
+		return -EINVAL;
+
+	/*
+	 * Bypassing the fb pitch check for VLV/HSW, as purportedly there
+	 * is a dynamic flip support in VLV/HSW. This will allow to
+	 * flip fbs of different resolutions without doing a modeset.
+	 * TBD, confirm the same for other newer gen platforms also.
+	 */
+	if (INTEL_INFO(dev)->gen > 3 &&
+	    !IS_VALLEYVIEW(dev) && !IS_HASWELL(dev) &&
+	    (fb->pitches[0] != crtc->primary->fb->pitches[0]))
 		return -EINVAL;
 
 	if (i915_terminally_wedged(&dev_priv->gpu_error))
@@ -10422,11 +10432,71 @@ out_config:
 	return ret;
 }
 
+static void intel_create_crtc_properties(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	if (!dev_priv->input_size_property)
+		dev_priv->input_size_property =
+			drm_property_create_range(dev, 0, "input size",
+						  0, UINT_MAX);
+
+	if (dev_priv->input_size_property)
+		drm_object_attach_property(&intel_crtc->base.base,
+					   dev_priv->input_size_property,
+					   0);
+}
+
 static int intel_crtc_set_property(struct drm_crtc *crtc,
 		struct drm_property *property, uint64_t val)
 {
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int ret = -ENOENT;
 
+	if (property == dev_priv->input_size_property) {
+		int new_width = (int)((val >> 16) & 0xffff);
+		int new_height = (int)(val & 0xffff);
+		const struct drm_display_mode *adjusted_mode =
+				&intel_crtc->config.adjusted_mode;
+
+		if ((new_width == intel_crtc->config.pipe_src_w) &&
+		    (new_height == intel_crtc->config.pipe_src_h))
+			return 0;
+
+		if (((adjusted_mode->crtc_hdisplay != new_width) ||
+		     (adjusted_mode->crtc_vdisplay != new_height)) &&
+		    ((HAS_PCH_SPLIT(dev) &&
+			(!intel_crtc->config.pch_pfit.enabled)) ||
+		     (!HAS_PCH_SPLIT(dev) &&
+			(!intel_crtc->config.gmch_pfit.control)))) {
+			DRM_ERROR("PIPESRC mismatch with Pipe timings &"
+				  "PF is disabled\n");
+			return -EINVAL;
+		}
+
+		intel_crtc->config.pipe_src_w = new_width;
+		intel_crtc->config.pipe_src_h = new_height;
+
+		intel_crtc->config.requested_mode.hdisplay = new_width;
+		intel_crtc->config.requested_mode.vdisplay = new_height;
+
+		crtc->mode.hdisplay = new_width;
+		crtc->mode.vdisplay = new_height;
+
+		/* pipesrc controls the size that is scaled from, which should
+		* always be the user's requested size.
+		*/
+		I915_WRITE(PIPESRC(intel_crtc->pipe),
+			((intel_crtc->config.pipe_src_w - 1) << 16) |
+			 (intel_crtc->config.pipe_src_h - 1));
+
+		return 0;
+	}
+
 	return ret;
 }
 
@@ -10577,6 +10647,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
+
+	intel_create_crtc_properties(&intel_crtc->base);
 }
 
 enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
