diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f09b752..328efac 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -5169,3 +5169,10 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
 					   supported_rotations);
 }
 EXPORT_SYMBOL(drm_mode_create_rotation_property);
+
+struct drm_property *drm_mode_create_crtc_size_property(struct drm_device *dev)
+{
+	return drm_property_create_range(dev, 0, "crtc size",
+					   0, UINT_MAX);
+}
+EXPORT_SYMBOL(drm_mode_create_crtc_size_property);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 63d7b8e..6eb1949 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -307,6 +307,13 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 		struct drm_crtc *crtc = mode_set->crtc;
 		int ret;
 
+		if (dev->mode_config.crtc_size_property) {
+			crtc->crtc_w = crtc->crtc_h = 0;
+			drm_object_property_set_value(&crtc->base,
+				dev->mode_config.crtc_size_property,
+				0);
+		}
+
 		if (crtc->funcs->cursor_set) {
 			ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
 			if (ret)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a75d1a0..7c417fc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10183,6 +10183,12 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
 	pipe_config->pipe_src_w = pipe_config->requested_mode.crtc_hdisplay;
 	pipe_config->pipe_src_h = pipe_config->requested_mode.crtc_vdisplay;
 
+	/* Set the Pipe Src values as per the crtc size property values */
+	if (crtc->crtc_w && crtc->crtc_h) {
+		pipe_config->pipe_src_w = crtc->crtc_w;
+		pipe_config->pipe_src_h = crtc->crtc_h;
+	}
+
 encoder_retry:
 	/* Ensure the port clock defaults are reset when retrying. */
 	pipe_config->port_clock = 0;
@@ -11438,11 +11444,67 @@ out_config:
 	return ret;
 }
 
+static int intel_crtc_set_property(struct drm_crtc *crtc,
+				    struct drm_property *prop,
+				    uint64_t val)
+{
+	struct drm_device *dev = crtc->dev;
+	int ret = -ENOENT;
+
+	if (prop == dev->mode_config.crtc_size_property) {
+		int old_width, old_height;
+		int new_width = (int)((val >> 16) & 0xffff);
+		int new_height = (int)(val & 0xffff);
+		const struct drm_framebuffer *fb = crtc->primary->fb;
+
+		if ((new_width == crtc->crtc_w) &&
+		    (new_height == crtc->crtc_h))
+			return 0;
+
+		/* Check if property is resetted, so just return */
+		if ((new_width == 0) && (new_height) == 0) {
+			crtc->crtc_w = crtc->crtc_h = 0;
+			/* FIXME, Is modeset required here ?. Actually the
+			   current FB may not be compatible with the mode */
+			return 0;
+		} else if ((new_width == 0) || (new_height == 0))
+			return -EINVAL;
+
+		/* Check if the current FB is compatible with new requested
+		   Pipesrc values by the User */
+		if (new_width > fb->width ||
+			new_height > fb->height ||
+			crtc->x > fb->width - new_width ||
+			crtc->y > fb->height - new_height) {
+			DRM_DEBUG_KMS("New Pipe Src values %dx%d is incompatible with current fb size & viewport %ux%u+%d+%d\n",
+			      new_width, new_height, fb->width, fb->height, crtc->x, crtc->y);
+			return -EINVAL;
+		}
+
+		old_width = crtc->crtc_w;
+		old_height = crtc->crtc_h;
+
+		crtc->crtc_w = new_width;
+		crtc->crtc_h = new_height;
+
+		/* Currently do a modeset always, this will also
+		 * enable & configure the Panel fitter accordingly */
+		ret = intel_crtc_restore_mode(crtc);
+		if (ret) {
+			crtc->crtc_w = old_width;
+			crtc->crtc_h = old_height;
+		}
+	}
+
+	return ret;
+}
+
 static const struct drm_crtc_funcs intel_crtc_funcs = {
 	.gamma_set = intel_crtc_gamma_set,
 	.set_config = intel_crtc_set_config,
 	.destroy = intel_crtc_destroy,
 	.page_flip = intel_crtc_page_flip,
+	.set_property = intel_crtc_set_property,
 };
 
 static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
@@ -11963,6 +12025,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
 	WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
+
+	if (!dev->mode_config.crtc_size_property)
+			dev->mode_config.crtc_size_property =
+				drm_mode_create_crtc_size_property(dev);
+
+	if (dev->mode_config.crtc_size_property)
+			drm_object_attach_property(&intel_crtc->base.base,
+				dev->mode_config.crtc_size_property,
+				0);
+
 	return;
 
 fail:
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0375d75..b409003 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -354,6 +354,11 @@ struct drm_crtc {
 	bool invert_dimensions;
 
 	int x, y;
+
+	/* Gets set only through the crtc_size property */
+	int crtc_w;
+	int crtc_h;
+
 	const struct drm_crtc_funcs *funcs;
 
 	/* CRTC gamma size for reporting to userspace */
@@ -826,6 +831,7 @@ struct drm_mode_config {
 	struct drm_property *path_property;
 	struct drm_property *plane_type_property;
 	struct drm_property *rotation_property;
+	struct drm_property *crtc_size_property;
 
 	/* DVI-I properties */
 	struct drm_property *dvi_i_subconnector_property;
@@ -1137,6 +1143,7 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);
 extern const char *drm_get_format_name(uint32_t format);
 extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
 							      unsigned int supported_rotations);
+extern struct drm_property *drm_mode_create_crtc_size_property(struct drm_device *dev);
 extern unsigned int drm_rotation_simplify(unsigned int rotation,
 					  unsigned int supported_rotations);
 
