diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 429677a111d5..b593612a917d 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -98,13 +98,6 @@ int intel_atomic_check(struct drm_device *dev,
 		return -EINVAL;
 	}
 
-	if (crtc_state &&
-	    crtc_state->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
-		ret = drm_atomic_add_affected_planes(state, &nuclear_crtc->base);
-		if (ret)
-			return ret;
-	}
-
 	ret = drm_atomic_helper_check_planes(dev, state);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index eb7c2e2819b7..fa1102392eca 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -109,6 +109,7 @@ static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_cr
 	struct intel_crtc_state *crtc_state);
 static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
 			   int num_connectors);
+static void intel_pre_disable_primary(struct drm_crtc *crtc);
 
 static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
 {
@@ -2582,11 +2583,12 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
 {
 	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *c;
-	struct intel_crtc *i;
 	struct drm_i915_gem_object *obj;
-	struct drm_plane *primary = intel_crtc->base.primary;
 	struct drm_framebuffer *fb;
+	struct drm_plane *primary = intel_crtc->base.primary;
+	struct intel_plane *p;
+	struct intel_plane_state *plane_state =
+		to_intel_plane_state(primary->state);
 
 	if (!plane_config->fb)
 		return;
@@ -2602,16 +2604,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
 	 * Failed to alloc the obj, check to see if we should share
 	 * an fb with another CRTC instead
 	 */
-	for_each_crtc(dev, c) {
-		i = to_intel_crtc(c);
-
-		if (c == &intel_crtc->base)
-			continue;
-
-		if (!i->active)
+	for_each_intel_plane(dev, p) {
+		if (p->base.type != DRM_PLANE_TYPE_PRIMARY)
 			continue;
 
-		fb = c->primary->fb;
+		fb = p->base.state->fb;
 		if (!fb)
 			continue;
 
@@ -2622,18 +2619,28 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
 		}
 	}
 
+	intel_pre_disable_primary(&intel_crtc->base);
+	to_intel_plane(primary)->disable_plane(primary, &intel_crtc->base);
+
 	return;
 
 valid_fb:
+	drm_framebuffer_reference(fb);
+	primary->fb = plane_state->base.fb = fb;
+	plane_state->base.crtc = primary->crtc = &intel_crtc->base;
+
+	plane_state->base.src_x = plane_state->base.src_y = 0;
+	plane_state->base.src_w = fb->width << 16;
+	plane_state->base.src_h = fb->height << 16;
+
+	plane_state->base.crtc_x = plane_state->base.src_y = 0;
+	plane_state->base.crtc_w = fb->width;
+	plane_state->base.crtc_h = fb->height;
+
+	plane_state->visible = true;
 	obj = intel_fb_obj(fb);
 	if (obj->tiling_mode != I915_TILING_NONE)
 		dev_priv->preserve_bios_swizzle = true;
-
-	primary->fb = fb;
-	primary->crtc = primary->state->crtc = &intel_crtc->base;
-	update_state_fb(primary);
-	intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
-	obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit;
 }
 
 static void i9xx_update_primary_plane(struct drm_crtc *crtc,
@@ -11761,34 +11768,6 @@ static bool check_encoder_cloning(struct drm_atomic_state *state,
 	return true;
 }
 
-static void intel_crtc_check_initial_planes(struct drm_crtc *crtc,
-					    struct drm_crtc_state *crtc_state)
-{
-	struct intel_crtc_state *pipe_config =
-		to_intel_crtc_state(crtc_state);
-	struct drm_plane *p;
-	unsigned visible_mask = 0;
-
-	drm_for_each_plane_mask(p, crtc->dev, crtc_state->plane_mask) {
-		struct drm_plane_state *plane_state =
-			drm_atomic_get_existing_plane_state(crtc_state->state, p);
-
-		if (WARN_ON(!plane_state))
-			continue;
-
-		if (!plane_state->fb)
-			crtc_state->plane_mask &=
-				~(1 << drm_plane_index(p));
-		else if (to_intel_plane_state(plane_state)->visible)
-			visible_mask |= 1 << drm_plane_index(p);
-	}
-
-	if (!visible_mask)
-		return;
-
-	pipe_config->quirks &= ~PIPE_CONFIG_QUIRK_INITIAL_PLANES;
-}
-
 static int intel_crtc_atomic_check(struct drm_crtc *crtc,
 				   struct drm_crtc_state *crtc_state)
 {
@@ -11810,10 +11789,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
 		"[CRTC:%i] mismatch between state->active(%i) and crtc->active(%i)\n",
 		idx, crtc->state->active, intel_crtc->active);
 
-	/* plane mask is fixed up after all initial planes are calculated */
-	if (pipe_config->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES)
-		intel_crtc_check_initial_planes(crtc, crtc_state);
-
 	if (mode_changed && !crtc_state->active)
 		intel_crtc->atomic.update_wm_post = true;
 
@@ -13155,19 +13130,6 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
 			continue;
 		}
 
-		if (pipe_config->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
-			ret = drm_atomic_add_affected_planes(state, crtc);
-			if (ret)
-				return ret;
-
-			/*
-			 * We ought to handle i915.fastboot here.
-			 * If no modeset is required and the primary plane has
-			 * a fb, update the members of crtc_state as needed,
-			 * and run the necessary updates during vblank evasion.
-			 */
-		}
-
 		if (!needs_modeset(crtc_state)) {
 			if (!(pipe_config->quirks & PIPE_CONFIG_QUIRK_INHERITED_MODE))
 				continue;
@@ -15149,25 +15111,30 @@ void intel_modeset_init(struct drm_device *dev)
 	drm_modeset_unlock_all(dev);
 
 	for_each_intel_crtc(dev, crtc) {
-		if (!crtc->active)
+		struct intel_initial_plane_config plane_config;
+		struct drm_plane *plane;
+
+		if (!crtc->base.state->active)
 			continue;
 
+		/* disable all non-primary planes */
+		drm_for_each_plane_mask(plane, dev,
+					crtc->base.state->plane_mask)
+			if (plane->type != DRM_PLANE_TYPE_PRIMARY)
+				to_intel_plane(plane)->disable_plane(plane, &crtc->base);
+
+		crtc->base.state->plane_mask &=
+			1 << drm_plane_index(crtc->base.primary);
+
+		plane_config.fb = NULL;
+		dev_priv->display.get_initial_plane_config(crtc,
+							   &plane_config);
+
 		/*
-		 * Note that reserving the BIOS fb up front prevents us
-		 * from stuffing other stolen allocations like the ring
-		 * on top.  This prevents some ugliness at boot time, and
-		 * can even allow for smooth boot transitions if the BIOS
-		 * fb is large enough for the active pipe configuration.
+		 * If the fb is shared between multiple heads, we'll
+		 * just get the first one.
 		 */
-		if (dev_priv->display.get_initial_plane_config) {
-			dev_priv->display.get_initial_plane_config(crtc,
-							   &crtc->plane_config);
-			/*
-			 * If the fb is shared between multiple heads, we'll
-			 * just get the first one.
-			 */
-			intel_find_initial_plane_obj(crtc, &crtc->plane_config);
-		}
+		intel_find_initial_plane_obj(crtc, &plane_config);
 	}
 }
 
@@ -15404,47 +15371,30 @@ static void readout_plane_state(struct intel_crtc *crtc,
 	struct intel_plane *p;
 	struct drm_plane_state *drm_plane_state;
 	bool active = crtc_state->base.active;
+	bool wrong_plane;
 
-	if (active) {
-		crtc_state->quirks |= PIPE_CONFIG_QUIRK_INITIAL_PLANES;
-
-		/* apply to previous sw state too */
-		to_intel_crtc_state(crtc->base.state)->quirks |=
-			PIPE_CONFIG_QUIRK_INITIAL_PLANES;
-	}
+	wrong_plane = active && !intel_check_plane_mapping(crtc);
+	if (wrong_plane)
+		crtc->pipe = !crtc->pipe;
 
 	for_each_intel_plane(crtc->base.dev, p) {
-		bool visible = active;
-
 		if (crtc->pipe != p->pipe)
 			continue;
 
 		drm_plane_state = p->base.state;
 
-		/* Plane scaler state is not touched here. The first atomic
-		 * commit will restore all plane scalers to its old state.
-		 */
-
-		if (active && p->base.type == DRM_PLANE_TYPE_PRIMARY) {
-			visible = primary_get_hw_state(crtc);
-			to_intel_plane_state(drm_plane_state)->visible = visible;
-		} else {
-			/*
-			 * unknown state, assume it's off to force a transition
-			 * to on when calculating state changes.
-			 */
+		if (p->base.type == DRM_PLANE_TYPE_PRIMARY)
+			to_intel_plane_state(drm_plane_state)->visible =
+				primary_get_hw_state(crtc);
+		else
 			to_intel_plane_state(drm_plane_state)->visible = false;
-		}
 
-		if (visible) {
-			crtc_state->base.plane_mask |=
-				1 << drm_plane_index(&p->base);
-		} else if (crtc_state->base.state) {
-			/* Make this unconditional for atomic hw readout. */
-			crtc_state->base.plane_mask &=
-				~(1 << drm_plane_index(&p->base));
-		}
+		crtc_state->base.plane_mask |=
+			1 << drm_plane_index(&p->base);
 	}
+
+	if (wrong_plane)
+		crtc->pipe = !crtc->pipe;
 }
 
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -15664,6 +15614,9 @@ void intel_modeset_gem_init(struct drm_device *dev)
 			update_state_fb(c->primary);
 			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
 		}
+		else
+			obj->frontbuffer_bits |=
+				to_intel_plane(c->primary)->frontbuffer_bit;
 	}
 
 	intel_backlight_register(dev);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2ed618f78fe6..c3cea178c809 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -341,7 +341,6 @@ struct intel_crtc_state {
 	 */
 #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS	(1<<0) /* unreliable sync mode.flags */
 #define PIPE_CONFIG_QUIRK_INHERITED_MODE	(1<<1) /* mode inherited from firmware */
-#define PIPE_CONFIG_QUIRK_INITIAL_PLANES	(1<<2) /* planes are in unknown state */
 	unsigned long quirks;
 
 	/* Pipe source size (ie. panel fitter input size)
@@ -550,7 +549,6 @@ struct intel_crtc {
 	uint32_t cursor_size;
 	uint32_t cursor_base;
 
-	struct intel_initial_plane_config plane_config;
 	struct intel_crtc_state *config;
 	bool new_enabled;
 
