diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index 86ba4b2..119439d 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -185,10 +185,12 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
 		 * 90/270 is not allowed with RGB64 16:16:16:16,
 		 * RGB 16-bit 5:6:5, and Indexed 8-bit.
 		 * TBD: Add RGB64 case once its added in supported format list.
+		 * TBD: Remove NV12, once its 90/270 remapping is supported
 		 */
 		switch (state->fb->pixel_format) {
 		case DRM_FORMAT_C8:
 		case DRM_FORMAT_RGB565:
+		case DRM_FORMAT_NV12:
 			DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
 					drm_get_format_name(state->fb->pixel_format));
 			return -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3ae646e..943a835 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3015,6 +3015,9 @@ u32 skl_plane_ctl_format(uint32_t pixel_format)
 	case DRM_FORMAT_VYUY:
 		plane_ctl_format = PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
 		break;
+	case DRM_FORMAT_NV12:
+		plane_ctl_format = PLANE_CTL_FORMAT_NV12;
+		break;
 	default:
 		BUG();
 	}
@@ -3085,6 +3088,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
 	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
 	int scaler_id = -1;
+	u32 aux_dist = 0, aux_x_offset = 0, aux_y_offset = 0, aux_stride = 0;
+	u32 tile_row_adjustment = 0;
 
 	plane_state = to_intel_plane_state(plane->state);
 
@@ -3141,11 +3146,34 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		x_offset = stride * tile_height - y - src_h;
 		y_offset = x;
 		plane_size = (src_w - 1) << 16 | (src_h - 1);
+		/*
+		 * TBD: For NV12 90/270 rotation, Y and UV subplanes should
+		 * be treated as separate surfaces and GTT remapping for
+		 * rotation should be done separately for each subplane.
+		 * Enable support once seperate remappings are available.
+		 */
 	} else {
 		stride = fb->pitches[0] / stride_div;
 		x_offset = x;
 		y_offset = y;
 		plane_size = (src_h - 1) << 16 | (src_w - 1);
+		tile_height = PAGE_SIZE / stride_div;
+
+		if (fb->pixel_format == DRM_FORMAT_NV12) {
+			int height_in_mem = (fb->offsets[1]/fb->pitches[0]);
+			/*
+			 * If UV starts from middle of a page, then UV start should
+			 * be programmed to beginning of that page. And offset into that
+			 * page to be programmed into y-offset
+			 */
+			tile_row_adjustment = height_in_mem % tile_height;
+			aux_dist = fb->pitches[0] * (height_in_mem - tile_row_adjustment);
+			aux_x_offset = DIV_ROUND_UP(x, 2);
+			aux_y_offset = DIV_ROUND_UP(y, 2) + tile_row_adjustment;
+			/* For tile-Yf, uv-subplane tile width is 2x of Y-subplane */
+			aux_stride = fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED ?
+				stride / 2 : stride;
+		}
 	}
 	plane_offset = y_offset << 16 | x_offset;
 
@@ -3153,11 +3181,14 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
 	I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
 	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
+	I915_WRITE(PLANE_AUX_DIST(pipe, 0), aux_dist | aux_stride);
+	I915_WRITE(PLANE_AUX_OFFSET(pipe, 0), aux_y_offset << 16 | aux_x_offset);
 
 	if (scaler_id >= 0) {
 		uint32_t ps_ctrl = 0;
 
 		WARN_ON(!dst_w || !dst_h);
+
 		ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(0) |
 			crtc_state->scaler_state.scalers[scaler_id].mode;
 		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
@@ -3166,6 +3197,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id), (dst_w << 16) | dst_h);
 		I915_WRITE(PLANE_POS(pipe, 0), 0);
 	} else {
+		WARN_ON(fb->pixel_format == DRM_FORMAT_NV12);
 		I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);
 	}
 
@@ -13090,6 +13122,12 @@ intel_check_primary_plane(struct drm_plane *plane,
 			intel_crtc->atomic.update_wm = true;
 	}
 
+	/* Adjust (macro)pixel boundary */
+	if (fb && format_is_yuv(fb->pixel_format)) {
+		src->x1 &= ~0x10000;
+		src->x2 &= ~0x10000;
+	}
+
 	if (INTEL_INFO(dev)->gen >= 9) {
 		ret = skl_update_scaler_users(intel_crtc, crtc_state,
 			to_intel_plane(plane), state, 0);
