diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 940f80b..d9004e8 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -607,6 +607,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
 		state->src_h = val;
 	} else if (property == config->rotation_property) {
 		state->rotation = val;
+	} else if (property == config->compression_property) {
+		state->compression = val;
 	} else if (plane->funcs->atomic_set_property) {
 		return plane->funcs->atomic_set_property(plane, state,
 				property, val);
@@ -654,6 +656,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = state->src_h;
 	} else if (property == config->rotation_property) {
 		*val = state->rotation;
+	} else if (property == config->compression_property) {
+		*val = state->compression;
 	} else if (plane->funcs->atomic_get_property) {
 		return plane->funcs->atomic_get_property(plane, state, property, val);
 	} else {
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 474f328..66f817b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -5778,6 +5778,22 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_mode_create_rotation_property);
 
+struct drm_property *drm_mode_create_compression_property(
+		struct drm_device *dev,
+		unsigned int comp_caps)
+{
+	static const struct drm_prop_enum_list props[] = {
+		{ DRM_COMP_NONE,   "Not compression capable" },
+		{ DRM_COMP_RENDER,  "Only render decompression" },
+	};
+
+	return drm_property_create_bitmask(dev, 0, "render compression",
+			props, ARRAY_SIZE(props),
+			comp_caps);
+}
+EXPORT_SYMBOL(drm_mode_create_compression_property);
+
+
 /**
  * DOC: Tile group
  *
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 59d6736..115736f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3120,8 +3120,47 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 
 			hphase = 0x00010001;  /* use trip for both Y and UV */
 			vphase = 0x00012000;  /* use trip for Y and phase 0.5 for UV */
+
+			/*
+			 * On SKL-C and BXT-A,
+			 * when the plane source pixel format is NV12,
+			 * the CHICKEN_PIPESL_* register bit 22 must be
+			 * set to 1
+			 */
+			if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
+					INTEL_REVID(dev) == SKL_REVID_C0))
+				I915_WRITE(CHICKEN_PIPESL_1(pipe),
+					I915_READ(CHICKEN_PIPESL_1(pipe)) |
+					HSW_FBCQ_DIS);
 		}
 	}
+
+	if (plane->state->compression) {
+		/*
+		 * FIXME: Check if aux_dist ad aux_stride can be taken as it
+		 * is from userspace.
+		 */
+		aux_dist = fb->offsets[1];
+		aux_stride = fb->pitches[1];
+		/*
+		 * For SKL and BXT,
+		 * When the render compression is enabled with plane
+		 * width greater than 3840 and horizontal panning,
+		 * the stride programmed in the PLANE_STRIDE register
+		 * must be multiple of 4.
+		 */
+		if (x > 3840 && x_offset != 0)
+			stride = stride - (stride % 4);
+		if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
+					INTEL_REVID(dev) == SKL_REVID_C0))
+			I915_WRITE(CHICKEN_PIPESL_1(pipe),
+					I915_READ(CHICKEN_PIPESL_1(pipe)) &
+					~HSW_FBCQ_DIS);
+		plane_ctl |= PLANE_CTL_DECOMPRESSION_ENABLE;
+	} else {
+		plane_ctl &= ~PLANE_CTL_DECOMPRESSION_ENABLE;
+	}
+
 	plane_offset = y_offset << 16 | x_offset;
 
 	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
@@ -11760,6 +11799,29 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 		    plane_state->rotation != BIT(DRM_ROTATE_0))
 			intel_crtc->atomic.disable_fbc = true;
 
+		if (INTEL_INFO(dev)->gen >= 9) {
+			if (plane_state->compression) {
+				ret = skl_check_compression(dev,
+					to_intel_plane(plane),
+					to_intel_plane_state(plane_state),
+					intel_crtc->pipe);
+				if (ret)
+					return ret;
+			}
+		}
+
+		/*
+		 * Disable FBC if render decompression has to be enabled.
+		 * FIXME: If FBC is disabled here because render decomp
+		 * has to be enabled, then in update_primary_plane(), if
+		 * render decomp is disabled for some reason, we need to
+		 * enable FBC ?
+		 */
+		if (IS_SKYLAKE(dev) && dev_priv->fbc.crtc == intel_crtc &&
+				plane_state->compression) {
+			intel_crtc->atomic.disable_fbc = true;
+		}
+
 		/*
 		 * BDW signals flip done immediately if the plane
 		 * is disabled, even if the plane enable is already
@@ -11778,6 +11840,16 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 			intel_crtc->atomic.update_sprite_watermarks |=
 				1 << i;
 		}
+		if (INTEL_INFO(dev)->gen >= 9) {
+			if (plane_state->compression) {
+				ret = skl_check_compression(dev,
+					to_intel_plane(plane),
+					to_intel_plane_state(plane_state),
+					intel_crtc->pipe);
+				if (ret)
+					return ret;
+			}
+		}
 	}
 	return 0;
 }
@@ -13495,6 +13567,88 @@ skl_max_scale(struct intel_crtc *intel_crtc,
 	return max_scale;
 }
 
+int skl_check_compression(struct drm_device *dev,
+		struct intel_plane *intel_plane,
+		struct intel_plane_state *plane_state,
+		enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_rect *src = &plane_state->src;
+	struct drm_framebuffer *fb;
+	int i;
+
+	fb = intel_plane ? plane_state->base.fb : NULL;
+
+	/*
+	 * TODO:
+	 * 1. Disable stereo 3D when render decomp is enabled (bit 7:6)
+	 * 2. Render decompression must not be used in VTd pass-through mode
+	 * 3. Program hashing select CHICKEN_MISC1 bit 15
+	 */
+
+	/*
+	 * On SKL A and SKL B,
+	 * Do not enable render decompression when the plane
+	 * width is smaller than 32 pixels or greater than
+	 * 2048 pixels
+	 */
+	if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) < SKL_REVID_C0)
+			&& ((src->x1 >> 16) > 2048))
+		plane_state->base.compression = DRM_COMP_NONE;
+
+	if (!plane_state->base.compression)
+		return -EINVAL;
+
+	/*
+	 * On SKL:*:C and BXT:*:A, there is a possible hang with NV12 format.
+	 * WA: When the plane source pixel format is NV12,
+	 * the CHICKEN_PIPESL_* register bit 22 must be set to 1 and the
+	 * render decompression must not be enabled on any of the planes in
+	 * that pipe.
+	 */
+	if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
+				INTEL_REVID(dev) == SKL_REVID_C0)) {
+		struct drm_plane *drm_plane;
+		struct drm_plane_state *state;
+
+		for_each_plane(dev_priv, pipe, i) {
+			drm_plane = drm_plane_from_index(dev, i);
+			if (drm_plane) {
+				state = drm_plane->state;
+				if (state) {
+					if (state->fb &&
+							state->fb->pixel_format
+							== DRM_FORMAT_NV12) {
+						plane_state->base.compression =
+							DRM_COMP_NONE;
+					}
+				}
+			}
+		}
+	}
+
+	if (!plane_state->base.compression)
+		return -EINVAL;
+
+	/*
+	 * Conditions to satisfy before enabling render decomp.
+	 * SKL+
+	 * Pipe A & B, Planes 1 & 2
+	 * RGB8888 Tile-Y format
+	 * 0/180 rotation
+	 */
+	if ((pipe == PIPE_C) ||
+			((fb->pixel_format != DRM_FORMAT_XRGB8888) &&
+			 (fb->pixel_format != DRM_FORMAT_ARGB8888)) ||
+			intel_rotation_90_or_270(plane_state->base.rotation) ||
+			((fb->modifier[0] == DRM_FORMAT_MOD_NONE) ||
+			 (fb->modifier[0] == I915_FORMAT_MOD_X_TILED))) {
+		plane_state->base.compression = DRM_COMP_NONE;
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int
 intel_check_primary_plane(struct drm_plane *plane,
 			  struct intel_crtc_state *crtc_state,
@@ -13670,11 +13824,31 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
 	if (INTEL_INFO(dev)->gen >= 4)
 		intel_create_rotation_property(dev, primary);
 
+	intel_create_compression_property(dev, primary);
+
 	drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
 
 	return &primary->base;
 }
 
+void intel_create_compression_property(struct drm_device *dev,
+		struct intel_plane *plane)
+{
+	/* Render compression is applicable only for plane 1 & 2 */
+	if (INTEL_INFO(dev)->gen >= 9 && (plane->plane <= 1)) {
+		if (!dev->mode_config.compression_property)
+			dev->mode_config.compression_property =
+				drm_mode_create_compression_property(dev,
+						BIT(DRM_COMP_NONE) |
+						BIT(DRM_COMP_RENDER));
+
+		if (dev->mode_config.compression_property)
+			drm_object_attach_property(&plane->base.base,
+					dev->mode_config.compression_property,
+					plane->base.state->compression);
+	}
+}
+
 void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane)
 {
 	if (!dev->mode_config.rotation_property) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 6cd6cb0..bae22eb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1090,6 +1090,13 @@ intel_rotation_90_or_270(unsigned int rotation)
 void intel_create_rotation_property(struct drm_device *dev,
 					struct intel_plane *plane);
 
+void intel_create_compression_property(struct drm_device *dev,
+					struct intel_plane *plane);
+int skl_check_compression(struct drm_device *dev,
+			struct intel_plane *intel_plane,
+			struct intel_plane_state *plane_state,
+			enum pipe pipe);
+
 /* shared dpll functions */
 struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
 void assert_shared_dpll(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 2f9f856..c6cf4ad 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -275,8 +275,41 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 
 			hphase = 0x00010001;  /* use trip for both Y and UV */
 			vphase = 0x00012000;  /* use trip for Y and phase 0.5 for UV */
+
+			if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
+					INTEL_REVID(dev) == SKL_REVID_C0))
+				I915_WRITE(CHICKEN_PIPESL_1(pipe),
+					I915_READ(CHICKEN_PIPESL_1(pipe)) |
+					HSW_FBCQ_DIS);
 		}
 	}
+
+	if (drm_plane->state->compression) {
+		/*
+		 * FIXME: Check if aux_dist ad aux_stride can be taken as it
+		 * is from userspace.
+		 */
+		aux_dist = fb->offsets[1];
+		aux_stride = fb->pitches[1];
+		/*
+		 * For SKL and BXT,
+		 * When the render compression is enabled with plane
+		 * width greater than 3840 and horizontal panning,
+		 * the stride programmed in the PLANE_STRIDE register
+		 * must be multiple of 4.
+		 */
+		if (x > 3840 && x_offset != 0)
+			stride = stride - (stride % 4);
+		if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
+					INTEL_REVID(dev) == SKL_REVID_C0))
+			I915_WRITE(CHICKEN_PIPESL_1(pipe),
+					I915_READ(CHICKEN_PIPESL_1(pipe)) &
+					~HSW_FBCQ_DIS);
+		plane_ctl |= PLANE_CTL_DECOMPRESSION_ENABLE;
+	} else {
+		plane_ctl &= ~PLANE_CTL_DECOMPRESSION_ENABLE;
+	}
+
 	plane_offset = y_offset << 16 | x_offset;
 
 	I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
@@ -1217,6 +1250,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
 
 	intel_create_rotation_property(dev, intel_plane);
 
+	intel_create_compression_property(dev, intel_plane);
+
 	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
 
 out:
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 75f49c1..02a9aaa 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -93,6 +93,10 @@ static inline uint64_t I642U64(int64_t val)
 #define DRM_REFLECT_X	4
 #define DRM_REFLECT_Y	5
 
+/* render compression property bits */
+#define DRM_COMP_NONE		0
+#define DRM_COMP_RENDER		1
+
 enum drm_connector_force {
 	DRM_FORCE_UNSPECIFIED,
 	DRM_FORCE_OFF,
@@ -783,6 +787,9 @@ struct drm_plane_state {
 	/* Plane rotation */
 	unsigned int rotation;
 
+	/* Render compression */
+	unsigned int compression;
+
 	struct drm_atomic_state *state;
 };
 
@@ -1114,6 +1121,7 @@ struct drm_mode_config {
 	struct drm_property *tile_property;
 	struct drm_property *plane_type_property;
 	struct drm_property *rotation_property;
+	struct drm_property *compression_property;
 	struct drm_property *prop_src_x;
 	struct drm_property *prop_src_y;
 	struct drm_property *prop_src_w;
@@ -1507,6 +1515,9 @@ 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_compression_property(
+				struct drm_device *dev,
+				unsigned int comp_caps);
 extern unsigned int drm_rotation_simplify(unsigned int rotation,
 					  unsigned int supported_rotations);
 
