All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [RFC v2] refactor intel display a bit more
@ 2020-12-10  4:17 Dave Airlie
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 1/9] drm/i915/display: move needs_modeset to an inline in header Dave Airlie
                   ` (14 more replies)
  0 siblings, 15 replies; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

The first 3 are just moving some functions to inline and fixing
a wrong comma, the next 4 are cleaned up from yesterday.

hsw fdi is definitely a WIP.

Skl planes migration is along the lines of what danvet asked for.

Dave.


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 1/9] drm/i915/display: move needs_modeset to an inline in header
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10 15:08   ` Ville Syrjälä
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 2/9] drm/i915/display: move to_intel_frontbuffer to header Dave Airlie
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

This function is going to be used in a later change, so clean it
up first before moving it.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/display/intel_display.c  | 78 +++++++++----------
 .../drm/i915/display/intel_display_types.h    |  6 ++
 2 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index c567c0cada7e..80103211f407 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -542,12 +542,6 @@ icl_wa_scalerclkgating(struct drm_i915_private *dev_priv, enum pipe pipe,
 		               intel_de_read(dev_priv, CLKGATE_DIS_PSL(pipe)) & ~DPFR_GATING_DIS);
 }
 
-static bool
-needs_modeset(const struct intel_crtc_state *state)
-{
-	return drm_atomic_crtc_needs_modeset(&state->uapi);
-}
-
 static bool
 is_trans_port_sync_slave(const struct intel_crtc_state *crtc_state)
 {
@@ -6474,7 +6468,7 @@ static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_s
 	if (!old_crtc_state->ips_enabled)
 		return false;
 
-	if (needs_modeset(new_crtc_state))
+	if (intel_crtc_needs_modeset(new_crtc_state))
 		return true;
 
 	/*
@@ -6501,7 +6495,7 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s
 	if (!new_crtc_state->ips_enabled)
 		return false;
 
-	if (needs_modeset(new_crtc_state))
+	if (intel_crtc_needs_modeset(new_crtc_state))
 		return true;
 
 	/*
@@ -6554,7 +6548,7 @@ static bool needs_scalerclk_wa(const struct intel_crtc_state *crtc_state)
 static bool planes_enabling(const struct intel_crtc_state *old_crtc_state,
 			    const struct intel_crtc_state *new_crtc_state)
 {
-	return (!old_crtc_state->active_planes || needs_modeset(new_crtc_state)) &&
+	return (!old_crtc_state->active_planes || intel_crtc_needs_modeset(new_crtc_state)) &&
 		new_crtc_state->active_planes;
 }
 
@@ -6562,7 +6556,7 @@ static bool planes_disabling(const struct intel_crtc_state *old_crtc_state,
 			     const struct intel_crtc_state *new_crtc_state)
 {
 	return old_crtc_state->active_planes &&
-		(!new_crtc_state->active_planes || needs_modeset(new_crtc_state));
+		(!new_crtc_state->active_planes || intel_crtc_needs_modeset(new_crtc_state));
 }
 
 static void intel_post_plane_update(struct intel_atomic_state *state,
@@ -6685,7 +6679,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
 	 * If we're doing a modeset we don't need to do any
 	 * pre-vblank watermark programming here.
 	 */
-	if (!needs_modeset(new_crtc_state)) {
+	if (!intel_crtc_needs_modeset(new_crtc_state)) {
 		/*
 		 * For platforms that support atomic watermarks, program the
 		 * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these
@@ -12046,7 +12040,7 @@ static void i9xx_update_cursor(struct intel_plane *plane,
 	if (INTEL_GEN(dev_priv) >= 9)
 		skl_write_cursor_wm(plane, crtc_state);
 
-	if (!needs_modeset(crtc_state))
+	if (!intel_crtc_needs_modeset(crtc_state))
 		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
 
 	if (plane->cursor.base != base ||
@@ -12616,7 +12610,7 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	bool mode_changed = needs_modeset(crtc_state);
+	bool mode_changed = intel_crtc_needs_modeset(crtc_state);
 	bool was_crtc_enabled = old_crtc_state->hw.active;
 	bool is_crtc_enabled = crtc_state->hw.active;
 	bool turn_off, turn_on, visible, was_visible;
@@ -12980,7 +12974,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct intel_crtc_state *crtc_state =
 		intel_atomic_get_new_crtc_state(state, crtc);
-	bool mode_changed = needs_modeset(crtc_state);
+	bool mode_changed = intel_crtc_needs_modeset(crtc_state);
 	int ret;
 
 	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv) &&
@@ -14812,7 +14806,7 @@ intel_modeset_verify_crtc(struct intel_crtc *crtc,
 			  struct intel_crtc_state *old_crtc_state,
 			  struct intel_crtc_state *new_crtc_state)
 {
-	if (!needs_modeset(new_crtc_state) && !new_crtc_state->update_pipe)
+	if (!intel_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->update_pipe)
 		return;
 
 	verify_wm_state(crtc, new_crtc_state);
@@ -14907,7 +14901,7 @@ static void intel_modeset_clear_plls(struct intel_atomic_state *state)
 		return;
 
 	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
-		if (!needs_modeset(new_crtc_state))
+		if (!intel_crtc_needs_modeset(new_crtc_state))
 			continue;
 
 		intel_release_shared_dplls(state, crtc);
@@ -14932,7 +14926,7 @@ static int hsw_mode_set_planes_workaround(struct intel_atomic_state *state)
 	/* look at all crtc's that are going to be enabled in during modeset */
 	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
 		if (!crtc_state->hw.active ||
-		    !needs_modeset(crtc_state))
+		    !intel_crtc_needs_modeset(crtc_state))
 			continue;
 
 		if (first_crtc_state) {
@@ -14957,7 +14951,7 @@ static int hsw_mode_set_planes_workaround(struct intel_atomic_state *state)
 		crtc_state->hsw_workaround_pipe = INVALID_PIPE;
 
 		if (!crtc_state->hw.active ||
-		    needs_modeset(crtc_state))
+		    intel_crtc_needs_modeset(crtc_state))
 			continue;
 
 		/* 2 or more enabled crtcs means no need for w/a */
@@ -15276,7 +15270,7 @@ static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state,
 	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
 		if (new_crtc_state->hw.enable &&
 		    transcoders & BIT(new_crtc_state->cpu_transcoder) &&
-		    needs_modeset(new_crtc_state))
+		    intel_crtc_needs_modeset(new_crtc_state))
 			return true;
 	}
 
@@ -15297,7 +15291,7 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state,
 		slave = crtc;
 		master = old_crtc_state->bigjoiner_linked_crtc;
 		master_crtc_state = intel_atomic_get_new_crtc_state(state, master);
-		if (!master_crtc_state || !needs_modeset(master_crtc_state))
+		if (!master_crtc_state || !intel_crtc_needs_modeset(master_crtc_state))
 			goto claimed;
 	}
 
@@ -15376,7 +15370,7 @@ static int intel_atomic_check_async(struct intel_atomic_state *state)
 
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (needs_modeset(new_crtc_state)) {
+		if (intel_crtc_needs_modeset(new_crtc_state)) {
 			drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n");
 			return -EINVAL;
 		}
@@ -15499,7 +15493,7 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
 		if (IS_ERR(linked_crtc_state))
 			return PTR_ERR(linked_crtc_state);
 
-		if (!needs_modeset(crtc_state))
+		if (!intel_crtc_needs_modeset(crtc_state))
 			continue;
 
 		linked_crtc_state->uapi.mode_changed = true;
@@ -15516,7 +15510,7 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
 
 	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
 		/* Kill old bigjoiner link, we may re-establish afterwards */
-		if (needs_modeset(crtc_state) &&
+		if (intel_crtc_needs_modeset(crtc_state) &&
 		    crtc_state->bigjoiner && !crtc_state->bigjoiner_slave)
 			kill_bigjoiner_slave(state, crtc_state);
 	}
@@ -15555,7 +15549,7 @@ static int intel_atomic_check(struct drm_device *dev,
 
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (!needs_modeset(new_crtc_state)) {
+		if (!intel_crtc_needs_modeset(new_crtc_state)) {
 			/* Light copy */
 			intel_crtc_copy_uapi_to_hw_state_nomodeset(state, new_crtc_state);
 
@@ -15586,7 +15580,7 @@ static int intel_atomic_check(struct drm_device *dev,
 
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (!needs_modeset(new_crtc_state))
+		if (!intel_crtc_needs_modeset(new_crtc_state))
 			continue;
 
 		ret = intel_modeset_pipe_config_late(new_crtc_state);
@@ -15608,7 +15602,7 @@ static int intel_atomic_check(struct drm_device *dev,
 	 * forced a full modeset.
 	 */
 	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
-		if (!new_crtc_state->hw.enable || needs_modeset(new_crtc_state))
+		if (!new_crtc_state->hw.enable || intel_crtc_needs_modeset(new_crtc_state))
 			continue;
 
 		if (intel_dp_mst_is_slave_trans(new_crtc_state)) {
@@ -15636,7 +15630,7 @@ static int intel_atomic_check(struct drm_device *dev,
 			struct intel_crtc_state *linked_crtc_state =
 				intel_atomic_get_new_crtc_state(state, new_crtc_state->bigjoiner_linked_crtc);
 
-			if (needs_modeset(linked_crtc_state)) {
+			if (intel_crtc_needs_modeset(linked_crtc_state)) {
 				new_crtc_state->uapi.mode_changed = true;
 				new_crtc_state->update_pipe = false;
 			}
@@ -15645,7 +15639,7 @@ static int intel_atomic_check(struct drm_device *dev,
 
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (needs_modeset(new_crtc_state)) {
+		if (intel_crtc_needs_modeset(new_crtc_state)) {
 			any_ms = true;
 			continue;
 		}
@@ -15722,12 +15716,12 @@ static int intel_atomic_check(struct drm_device *dev,
 				goto fail;
 		}
 
-		if (!needs_modeset(new_crtc_state) &&
+		if (!intel_crtc_needs_modeset(new_crtc_state) &&
 		    !new_crtc_state->update_pipe)
 			continue;
 
 		intel_dump_pipe_config(new_crtc_state, state,
-				       needs_modeset(new_crtc_state) ?
+				       intel_crtc_needs_modeset(new_crtc_state) ?
 				       "[modeset]" : "[fastset]");
 	}
 
@@ -15759,7 +15753,7 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
 		return ret;
 
 	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-		bool mode_changed = needs_modeset(crtc_state);
+		bool mode_changed = intel_crtc_needs_modeset(crtc_state);
 
 		if (mode_changed || crtc_state->update_pipe ||
 		    crtc_state->uapi.color_mgmt_changed) {
@@ -15850,7 +15844,7 @@ static void commit_pipe_config(struct intel_atomic_state *state,
 		intel_atomic_get_old_crtc_state(state, crtc);
 	const struct intel_crtc_state *new_crtc_state =
 		intel_atomic_get_new_crtc_state(state, crtc);
-	bool modeset = needs_modeset(new_crtc_state);
+	bool modeset = intel_crtc_needs_modeset(new_crtc_state);
 
 	/*
 	 * During modesets pipe configuration was programmed as the
@@ -15884,7 +15878,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
 	const struct intel_crtc_state *new_crtc_state =
 		intel_atomic_get_new_crtc_state(state, crtc);
 
-	if (!needs_modeset(new_crtc_state))
+	if (!intel_crtc_needs_modeset(new_crtc_state))
 		return;
 
 	intel_crtc_update_active_timings(new_crtc_state);
@@ -15906,7 +15900,7 @@ static void intel_update_crtc(struct intel_atomic_state *state,
 		intel_atomic_get_old_crtc_state(state, crtc);
 	struct intel_crtc_state *new_crtc_state =
 		intel_atomic_get_new_crtc_state(state, crtc);
-	bool modeset = needs_modeset(new_crtc_state);
+	bool modeset = intel_crtc_needs_modeset(new_crtc_state);
 
 	if (!modeset) {
 		if (new_crtc_state->preload_luts &&
@@ -15998,7 +15992,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
 	/* Only disable port sync and MST slaves */
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (!needs_modeset(new_crtc_state) || old_crtc_state->bigjoiner)
+		if (!intel_crtc_needs_modeset(new_crtc_state) || old_crtc_state->bigjoiner)
 			continue;
 
 		if (!old_crtc_state->hw.active)
@@ -16022,7 +16016,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
 	/* Disable everything else left on */
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (!needs_modeset(new_crtc_state) ||
+		if (!intel_crtc_needs_modeset(new_crtc_state) ||
 		    (handled & BIT(crtc->pipe)) ||
 		    old_crtc_state->bigjoiner_slave)
 			continue;
@@ -16072,7 +16066,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 			continue;
 
 		/* ignore allocations for crtc's that have been turned off. */
-		if (!needs_modeset(new_crtc_state)) {
+		if (!intel_crtc_needs_modeset(new_crtc_state)) {
 			entries[pipe] = old_crtc_state->wm.skl.ddb;
 			update_pipes |= BIT(pipe);
 		} else {
@@ -16267,7 +16261,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (needs_modeset(new_crtc_state) ||
+		if (intel_crtc_needs_modeset(new_crtc_state) ||
 		    new_crtc_state->update_pipe) {
 
 			put_domains[crtc->pipe] =
@@ -16293,7 +16287,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 
 	/* Complete the events for pipes that have now been disabled */
 	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
-		bool modeset = needs_modeset(new_crtc_state);
+		bool modeset = intel_crtc_needs_modeset(new_crtc_state);
 
 		/* Complete events for now disable pipes here. */
 		if (modeset && !new_crtc_state->hw.active && new_crtc_state->uapi.event) {
@@ -16341,7 +16335,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 			skl_disable_flip_done(crtc);
 
 		if (new_crtc_state->hw.active &&
-		    !needs_modeset(new_crtc_state) &&
+		    !intel_crtc_needs_modeset(new_crtc_state) &&
 		    !new_crtc_state->preload_luts &&
 		    (new_crtc_state->uapi.color_mgmt_changed ||
 		     new_crtc_state->update_pipe))
@@ -16712,7 +16706,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
 		 * This should only fail upon a hung GPU, in which case we
 		 * can safely continue.
 		 */
-		if (needs_modeset(crtc_state)) {
+		if (intel_crtc_needs_modeset(crtc_state)) {
 			ret = i915_sw_fence_await_reservation(&state->commit_ready,
 							      old_obj->base.resv, NULL,
 							      false, 0,
@@ -16937,7 +16931,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
 	 *
 	 * FIXME bigjoiner fastpath would be good
 	 */
-	if (!crtc_state->hw.active || needs_modeset(crtc_state) ||
+	if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
 	    crtc_state->update_pipe || crtc_state->bigjoiner)
 		goto slow;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 5bc5bfbc4551..8c4afad68a44 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1777,6 +1777,12 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
 		 (1 << INTEL_OUTPUT_EDP));
 }
 
+static inline bool
+intel_crtc_needs_modeset(const struct intel_crtc_state *state)
+{
+	return drm_atomic_crtc_needs_modeset(&state->uapi);
+}
+
 static inline void
 intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 2/9] drm/i915/display: move to_intel_frontbuffer to header
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 1/9] drm/i915/display: move needs_modeset to an inline in header Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10 15:08   ` Ville Syrjälä
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 3/9] drm/i915/display: fix misused comma Dave Airlie
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

This will be used for some refactoring in other files, so move it
first.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/display/intel_display.c       | 6 ------
 drivers/gpu/drm/i915/display/intel_display_types.h | 6 ++++++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 80103211f407..62e22d832cab 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3611,12 +3611,6 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
 	intel_disable_plane(plane, crtc_state);
 }
 
-static struct intel_frontbuffer *
-to_intel_frontbuffer(struct drm_framebuffer *fb)
-{
-	return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
-}
-
 static void
 intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
 			     struct intel_initial_plane_config *plane_config)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 8c4afad68a44..dfe573c8b5ae 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1805,4 +1805,10 @@ static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
 	return i915_ggtt_offset(state->vma);
 }
 
+static inline struct intel_frontbuffer *
+to_intel_frontbuffer(struct drm_framebuffer *fb)
+{
+	return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
+}
+
 #endif /*  __INTEL_DISPLAY_TYPES_H__ */
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 3/9] drm/i915/display: fix misused comma
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 1/9] drm/i915/display: move needs_modeset to an inline in header Dave Airlie
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 2/9] drm/i915/display: move to_intel_frontbuffer to header Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10 15:09   ` Ville Syrjälä
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c Dave Airlie
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

There is no need for a comma use here.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 62e22d832cab..79d7479beed2 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -989,7 +989,8 @@ chv_find_best_dpll(const struct intel_limit *limit,
 	 * set to 2.  If requires to support 200Mhz refclk, we need to
 	 * revisit this because n may not 1 anymore.
 	 */
-	clock.n = 1, clock.m1 = 2;
+	clock.n = 1;
+	clock.m1 = 2;
 	target *= 5;	/* fast clock */
 
 	for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (2 preceding siblings ...)
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 3/9] drm/i915/display: fix misused comma Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10 15:06   ` Ville Syrjälä
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 5/9] drm/i915: refactor some crtc code out of intel display Dave Airlie
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

This file is a monster, let's start simple, the cursor plane code
seems pretty standalone, and splits out easily enough.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/Makefile                |   1 +
 drivers/gpu/drm/i915/display/intel_cursor.c  | 805 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_display.c | 796 +-----------------
 drivers/gpu/drm/i915/display/intel_display.h |  12 +
 4 files changed, 824 insertions(+), 790 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cursor.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index e5574e506a5c..98a35b939052 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -197,6 +197,7 @@ i915-y += \
 	display/intel_combo_phy.o \
 	display/intel_connector.o \
 	display/intel_csr.o \
+	display/intel_cursor.o \
 	display/intel_display.o \
 	display/intel_display_power.o \
 	display/intel_dpio_phy.o \
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
new file mode 100644
index 000000000000..87a7a74a25ac
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -0,0 +1,805 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#include <linux/kernel.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_fourcc.h>
+
+#include "intel_atomic.h"
+#include "intel_atomic_plane.h"
+#include "intel_display_types.h"
+#include "intel_display.h"
+
+#include "intel_frontbuffer.h"
+#include "intel_pm.h"
+#include "intel_psr.h"
+#include "intel_sprite.h"
+
+/* Cursor formats */
+static const u32 intel_cursor_formats[] = {
+	DRM_FORMAT_ARGB8888,
+};
+
+static const u64 cursor_format_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->uapi.plane->dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	u32 base;
+
+	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
+		base = sg_dma_address(obj->mm.pages->sgl);
+	else
+		base = intel_plane_ggtt_offset(plane_state);
+
+	return base + plane_state->color_plane[0].offset;
+}
+
+static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
+{
+	int x = plane_state->uapi.dst.x1;
+	int y = plane_state->uapi.dst.y1;
+	u32 pos = 0;
+
+	if (x < 0) {
+		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
+		x = -x;
+	}
+	pos |= x << CURSOR_X_SHIFT;
+
+	if (y < 0) {
+		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
+		y = -y;
+	}
+	pos |= y << CURSOR_Y_SHIFT;
+
+	return pos;
+}
+
+static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
+{
+	const struct drm_mode_config *config =
+		&plane_state->uapi.plane->dev->mode_config;
+	int width = drm_rect_width(&plane_state->uapi.dst);
+	int height = drm_rect_height(&plane_state->uapi.dst);
+
+	return width > 0 && width <= config->cursor_width &&
+		height > 0 && height <= config->cursor_height;
+}
+
+static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->uapi.plane->dev);
+	unsigned int rotation = plane_state->hw.rotation;
+	int src_x, src_y;
+	u32 offset;
+	int ret;
+
+	ret = intel_plane_compute_gtt(plane_state);
+	if (ret)
+		return ret;
+
+	if (!plane_state->uapi.visible)
+		return 0;
+
+	src_x = plane_state->uapi.src.x1 >> 16;
+	src_y = plane_state->uapi.src.y1 >> 16;
+
+	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
+	offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
+						    plane_state, 0);
+
+	if (src_x != 0 || src_y != 0) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "Arbitrary cursor panning not supported\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Put the final coordinates back so that the src
+	 * coordinate checks will see the right values.
+	 */
+	drm_rect_translate_to(&plane_state->uapi.src,
+			      src_x << 16, src_y << 16);
+
+	/* ILK+ do this automagically in hardware */
+	if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
+		const struct drm_framebuffer *fb = plane_state->hw.fb;
+		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
+
+		offset += (src_h * src_w - 1) * fb->format->cpp[0];
+	}
+
+	plane_state->color_plane[0].offset = offset;
+	plane_state->color_plane[0].x = src_x;
+	plane_state->color_plane[0].y = src_y;
+
+	return 0;
+}
+
+static int intel_check_cursor(struct intel_crtc_state *crtc_state,
+			      struct intel_plane_state *plane_state)
+{
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+	const struct drm_rect src = plane_state->uapi.src;
+	const struct drm_rect dst = plane_state->uapi.dst;
+	int ret;
+
+	if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
+		drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
+		return -EINVAL;
+	}
+
+	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
+						DRM_PLANE_HELPER_NO_SCALING,
+						DRM_PLANE_HELPER_NO_SCALING,
+						true);
+	if (ret)
+		return ret;
+
+	/* Use the unclipped src/dst rectangles, which we program to hw */
+	plane_state->uapi.src = src;
+	plane_state->uapi.dst = dst;
+
+	ret = intel_cursor_check_surface(plane_state);
+	if (ret)
+		return ret;
+
+	if (!plane_state->uapi.visible)
+		return 0;
+
+	ret = intel_plane_check_src_coordinates(plane_state);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static unsigned int
+i845_cursor_max_stride(struct intel_plane *plane,
+		       u32 pixel_format, u64 modifier,
+		       unsigned int rotation)
+{
+	return 2048;
+}
+
+static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
+{
+	u32 cntl = 0;
+
+	if (crtc_state->gamma_enable)
+		cntl |= CURSOR_GAMMA_ENABLE;
+
+	return cntl;
+}
+
+static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
+			   const struct intel_plane_state *plane_state)
+{
+	return CURSOR_ENABLE |
+		CURSOR_FORMAT_ARGB |
+		CURSOR_STRIDE(plane_state->color_plane[0].stride);
+}
+
+static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
+{
+	int width = drm_rect_width(&plane_state->uapi.dst);
+
+	/*
+	 * 845g/865g are only limited by the width of their cursors,
+	 * the height is arbitrary up to the precision of the register.
+	 */
+	return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
+}
+
+static int i845_check_cursor(struct intel_crtc_state *crtc_state,
+			     struct intel_plane_state *plane_state)
+{
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+	int ret;
+
+	ret = intel_check_cursor(crtc_state, plane_state);
+	if (ret)
+		return ret;
+
+	/* if we want to turn off the cursor ignore width and height */
+	if (!fb)
+		return 0;
+
+	/* Check for which cursor types we support */
+	if (!i845_cursor_size_ok(plane_state)) {
+		drm_dbg_kms(&i915->drm,
+			    "Cursor dimension %dx%d not supported\n",
+			    drm_rect_width(&plane_state->uapi.dst),
+			    drm_rect_height(&plane_state->uapi.dst));
+		return -EINVAL;
+	}
+
+	drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
+		    plane_state->color_plane[0].stride != fb->pitches[0]);
+
+	switch (fb->pitches[0]) {
+	case 256:
+	case 512:
+	case 1024:
+	case 2048:
+		break;
+	default:
+		 drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
+			     fb->pitches[0]);
+		return -EINVAL;
+	}
+
+	plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
+
+	return 0;
+}
+
+static void i845_update_cursor(struct intel_plane *plane,
+			       const struct intel_crtc_state *crtc_state,
+			       const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	u32 cntl = 0, base = 0, pos = 0, size = 0;
+	unsigned long irqflags;
+
+	if (plane_state && plane_state->uapi.visible) {
+		unsigned int width = drm_rect_width(&plane_state->uapi.dst);
+		unsigned int height = drm_rect_height(&plane_state->uapi.dst);
+
+		cntl = plane_state->ctl |
+			i845_cursor_ctl_crtc(crtc_state);
+
+		size = (height << 12) | width;
+
+		base = intel_cursor_base(plane_state);
+		pos = intel_cursor_position(plane_state);
+	}
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	/* On these chipsets we can only modify the base/size/stride
+	 * whilst the cursor is disabled.
+	 */
+	if (plane->cursor.base != base ||
+	    plane->cursor.size != size ||
+	    plane->cursor.cntl != cntl) {
+		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
+		intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
+		intel_de_write_fw(dev_priv, CURSIZE, size);
+		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
+		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
+
+		plane->cursor.base = base;
+		plane->cursor.size = size;
+		plane->cursor.cntl = cntl;
+	} else {
+		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
+	}
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static void i845_disable_cursor(struct intel_plane *plane,
+				const struct intel_crtc_state *crtc_state)
+{
+	i845_update_cursor(plane, crtc_state, NULL);
+}
+
+static bool i845_cursor_get_hw_state(struct intel_plane *plane,
+				     enum pipe *pipe)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
+	bool ret;
+
+	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
+		return false;
+
+	ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
+
+	*pipe = PIPE_A;
+
+	intel_display_power_put(dev_priv, power_domain, wakeref);
+
+	return ret;
+}
+
+static unsigned int
+i9xx_cursor_max_stride(struct intel_plane *plane,
+		       u32 pixel_format, u64 modifier,
+		       unsigned int rotation)
+{
+	return plane->base.dev->mode_config.cursor_width * 4;
+}
+
+static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	u32 cntl = 0;
+
+	if (INTEL_GEN(dev_priv) >= 11)
+		return cntl;
+
+	if (crtc_state->gamma_enable)
+		cntl = MCURSOR_GAMMA_ENABLE;
+
+	if (crtc_state->csc_enable)
+		cntl |= MCURSOR_PIPE_CSC_ENABLE;
+
+	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
+		cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
+
+	return cntl;
+}
+
+static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
+			   const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->uapi.plane->dev);
+	u32 cntl = 0;
+
+	if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
+		cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
+
+	switch (drm_rect_width(&plane_state->uapi.dst)) {
+	case 64:
+		cntl |= MCURSOR_MODE_64_ARGB_AX;
+		break;
+	case 128:
+		cntl |= MCURSOR_MODE_128_ARGB_AX;
+		break;
+	case 256:
+		cntl |= MCURSOR_MODE_256_ARGB_AX;
+		break;
+	default:
+		MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
+		return 0;
+	}
+
+	if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
+		cntl |= MCURSOR_ROTATE_180;
+
+	return cntl;
+}
+
+static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->uapi.plane->dev);
+	int width = drm_rect_width(&plane_state->uapi.dst);
+	int height = drm_rect_height(&plane_state->uapi.dst);
+
+	if (!intel_cursor_size_ok(plane_state))
+		return false;
+
+	/* Cursor width is limited to a few power-of-two sizes */
+	switch (width) {
+	case 256:
+	case 128:
+	case 64:
+		break;
+	default:
+		return false;
+	}
+
+	/*
+	 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
+	 * height from 8 lines up to the cursor width, when the
+	 * cursor is not rotated. Everything else requires square
+	 * cursors.
+	 */
+	if (HAS_CUR_FBC(dev_priv) &&
+	    plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
+		if (height < 8 || height > width)
+			return false;
+	} else {
+		if (height != width)
+			return false;
+	}
+
+	return true;
+}
+
+static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
+			     struct intel_plane_state *plane_state)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	enum pipe pipe = plane->pipe;
+	int ret;
+
+	ret = intel_check_cursor(crtc_state, plane_state);
+	if (ret)
+		return ret;
+
+	/* if we want to turn off the cursor ignore width and height */
+	if (!fb)
+		return 0;
+
+	/* Check for which cursor types we support */
+	if (!i9xx_cursor_size_ok(plane_state)) {
+		drm_dbg(&dev_priv->drm,
+			"Cursor dimension %dx%d not supported\n",
+			drm_rect_width(&plane_state->uapi.dst),
+			drm_rect_height(&plane_state->uapi.dst));
+		return -EINVAL;
+	}
+
+	drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
+		    plane_state->color_plane[0].stride != fb->pitches[0]);
+
+	if (fb->pitches[0] !=
+	    drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "Invalid cursor stride (%u) (cursor width %d)\n",
+			    fb->pitches[0],
+			    drm_rect_width(&plane_state->uapi.dst));
+		return -EINVAL;
+	}
+
+	/*
+	 * There's something wrong with the cursor on CHV pipe C.
+	 * If it straddles the left edge of the screen then
+	 * moving it away from the edge or disabling it often
+	 * results in a pipe underrun, and often that can lead to
+	 * dead pipe (constant underrun reported, and it scans
+	 * out just a solid color). To recover from that, the
+	 * display power well must be turned off and on again.
+	 * Refuse the put the cursor into that compromised position.
+	 */
+	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
+	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "CHV cursor C not allowed to straddle the left screen edge\n");
+		return -EINVAL;
+	}
+
+	plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
+
+	return 0;
+}
+
+static void i9xx_update_cursor(struct intel_plane *plane,
+			       const struct intel_crtc_state *crtc_state,
+			       const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum pipe pipe = plane->pipe;
+	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
+	unsigned long irqflags;
+
+	if (plane_state && plane_state->uapi.visible) {
+		unsigned width = drm_rect_width(&plane_state->uapi.dst);
+		unsigned height = drm_rect_height(&plane_state->uapi.dst);
+
+		cntl = plane_state->ctl |
+			i9xx_cursor_ctl_crtc(crtc_state);
+
+		if (width != height)
+			fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
+
+		base = intel_cursor_base(plane_state);
+		pos = intel_cursor_position(plane_state);
+	}
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	/*
+	 * On some platforms writing CURCNTR first will also
+	 * cause CURPOS to be armed by the CURBASE write.
+	 * Without the CURCNTR write the CURPOS write would
+	 * arm itself. Thus we always update CURCNTR before
+	 * CURPOS.
+	 *
+	 * On other platforms CURPOS always requires the
+	 * CURBASE write to arm the update. Additonally
+	 * a write to any of the cursor register will cancel
+	 * an already armed cursor update. Thus leaving out
+	 * the CURBASE write after CURPOS could lead to a
+	 * cursor that doesn't appear to move, or even change
+	 * shape. Thus we always write CURBASE.
+	 *
+	 * The other registers are armed by by the CURBASE write
+	 * except when the plane is getting enabled at which time
+	 * the CURCNTR write arms the update.
+	 */
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		skl_write_cursor_wm(plane, crtc_state);
+
+	if (!intel_crtc_needs_modeset(crtc_state))
+		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
+
+	if (plane->cursor.base != base ||
+	    plane->cursor.size != fbc_ctl ||
+	    plane->cursor.cntl != cntl) {
+		if (HAS_CUR_FBC(dev_priv))
+			intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
+					  fbc_ctl);
+		intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
+		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
+		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
+
+		plane->cursor.base = base;
+		plane->cursor.size = fbc_ctl;
+		plane->cursor.cntl = cntl;
+	} else {
+		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
+		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
+	}
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static void i9xx_disable_cursor(struct intel_plane *plane,
+				const struct intel_crtc_state *crtc_state)
+{
+	i9xx_update_cursor(plane, crtc_state, NULL);
+}
+
+static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
+				     enum pipe *pipe)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
+	bool ret;
+	u32 val;
+
+	/*
+	 * Not 100% correct for planes that can move between pipes,
+	 * but that's only the case for gen2-3 which don't have any
+	 * display power wells.
+	 */
+	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
+		return false;
+
+	val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
+
+	ret = val & MCURSOR_MODE;
+
+	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		*pipe = plane->pipe;
+	else
+		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
+			MCURSOR_PIPE_SELECT_SHIFT;
+
+	intel_display_power_put(dev_priv, power_domain, wakeref);
+
+	return ret;
+}
+
+static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
+					      u32 format, u64 modifier)
+{
+	return modifier == DRM_FORMAT_MOD_LINEAR &&
+		format == DRM_FORMAT_ARGB8888;
+}
+
+static int
+intel_legacy_cursor_update(struct drm_plane *_plane,
+			   struct drm_crtc *_crtc,
+			   struct drm_framebuffer *fb,
+			   int crtc_x, int crtc_y,
+			   unsigned int crtc_w, unsigned int crtc_h,
+			   u32 src_x, u32 src_y,
+			   u32 src_w, u32 src_h,
+			   struct drm_modeset_acquire_ctx *ctx)
+{
+	struct intel_plane *plane = to_intel_plane(_plane);
+	struct intel_crtc *crtc = to_intel_crtc(_crtc);
+	struct intel_plane_state *old_plane_state =
+		to_intel_plane_state(plane->base.state);
+	struct intel_plane_state *new_plane_state;
+	struct intel_crtc_state *crtc_state =
+		to_intel_crtc_state(crtc->base.state);
+	struct intel_crtc_state *new_crtc_state;
+	int ret;
+
+	/*
+	 * When crtc is inactive or there is a modeset pending,
+	 * wait for it to complete in the slowpath
+	 *
+	 * FIXME bigjoiner fastpath would be good
+	 */
+	if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
+	    crtc_state->update_pipe || crtc_state->bigjoiner)
+		goto slow;
+
+	/*
+	 * Don't do an async update if there is an outstanding commit modifying
+	 * the plane.  This prevents our async update's changes from getting
+	 * overridden by a previous synchronous update's state.
+	 */
+	if (old_plane_state->uapi.commit &&
+	    !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
+		goto slow;
+
+	/*
+	 * If any parameters change that may affect watermarks,
+	 * take the slowpath. Only changing fb or position should be
+	 * in the fastpath.
+	 */
+	if (old_plane_state->uapi.crtc != &crtc->base ||
+	    old_plane_state->uapi.src_w != src_w ||
+	    old_plane_state->uapi.src_h != src_h ||
+	    old_plane_state->uapi.crtc_w != crtc_w ||
+	    old_plane_state->uapi.crtc_h != crtc_h ||
+	    !old_plane_state->uapi.fb != !fb)
+		goto slow;
+
+	new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
+	if (!new_plane_state)
+		return -ENOMEM;
+
+	new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
+	if (!new_crtc_state) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
+
+	new_plane_state->uapi.src_x = src_x;
+	new_plane_state->uapi.src_y = src_y;
+	new_plane_state->uapi.src_w = src_w;
+	new_plane_state->uapi.src_h = src_h;
+	new_plane_state->uapi.crtc_x = crtc_x;
+	new_plane_state->uapi.crtc_y = crtc_y;
+	new_plane_state->uapi.crtc_w = crtc_w;
+	new_plane_state->uapi.crtc_h = crtc_h;
+
+	intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
+
+	ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
+						  old_plane_state, new_plane_state);
+	if (ret)
+		goto out_free;
+
+	ret = intel_plane_pin_fb(new_plane_state);
+	if (ret)
+		goto out_free;
+
+	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
+				ORIGIN_FLIP);
+	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
+				to_intel_frontbuffer(new_plane_state->hw.fb),
+				plane->frontbuffer_bit);
+
+	/* Swap plane state */
+	plane->base.state = &new_plane_state->uapi;
+
+	/*
+	 * We cannot swap crtc_state as it may be in use by an atomic commit or
+	 * page flip that's running simultaneously. If we swap crtc_state and
+	 * destroy the old state, we will cause a use-after-free there.
+	 *
+	 * Only update active_planes, which is needed for our internal
+	 * bookkeeping. Either value will do the right thing when updating
+	 * planes atomically. If the cursor was part of the atomic update then
+	 * we would have taken the slowpath.
+	 */
+	crtc_state->active_planes = new_crtc_state->active_planes;
+
+	if (new_plane_state->uapi.visible)
+		intel_update_plane(plane, crtc_state, new_plane_state);
+	else
+		intel_disable_plane(plane, crtc_state);
+
+	intel_plane_unpin_fb(old_plane_state);
+
+out_free:
+	if (new_crtc_state)
+		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
+	if (ret)
+		intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
+	else
+		intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
+	return ret;
+
+slow:
+	return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
+					      crtc_x, crtc_y, crtc_w, crtc_h,
+					      src_x, src_y, src_w, src_h, ctx);
+}
+
+static const struct drm_plane_funcs intel_cursor_plane_funcs = {
+	.update_plane = intel_legacy_cursor_update,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = intel_plane_destroy,
+	.atomic_duplicate_state = intel_plane_duplicate_state,
+	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = intel_cursor_format_mod_supported,
+};
+
+struct intel_plane *
+intel_cursor_plane_create(struct drm_i915_private *dev_priv,
+			  enum pipe pipe)
+{
+	struct intel_plane *cursor;
+	int ret, zpos;
+
+	cursor = intel_plane_alloc();
+	if (IS_ERR(cursor))
+		return cursor;
+
+	cursor->pipe = pipe;
+	cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
+	cursor->id = PLANE_CURSOR;
+	cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
+
+	if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
+		cursor->max_stride = i845_cursor_max_stride;
+		cursor->update_plane = i845_update_cursor;
+		cursor->disable_plane = i845_disable_cursor;
+		cursor->get_hw_state = i845_cursor_get_hw_state;
+		cursor->check_plane = i845_check_cursor;
+	} else {
+		cursor->max_stride = i9xx_cursor_max_stride;
+		cursor->update_plane = i9xx_update_cursor;
+		cursor->disable_plane = i9xx_disable_cursor;
+		cursor->get_hw_state = i9xx_cursor_get_hw_state;
+		cursor->check_plane = i9xx_check_cursor;
+	}
+
+	cursor->cursor.base = ~0;
+	cursor->cursor.cntl = ~0;
+
+	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
+		cursor->cursor.size = ~0;
+
+	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
+				       0, &intel_cursor_plane_funcs,
+				       intel_cursor_formats,
+				       ARRAY_SIZE(intel_cursor_formats),
+				       cursor_format_modifiers,
+				       DRM_PLANE_TYPE_CURSOR,
+				       "cursor %c", pipe_name(pipe));
+	if (ret)
+		goto fail;
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		drm_plane_create_rotation_property(&cursor->base,
+						   DRM_MODE_ROTATE_0,
+						   DRM_MODE_ROTATE_0 |
+						   DRM_MODE_ROTATE_180);
+
+	zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
+	drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
+
+	if (INTEL_GEN(dev_priv) >= 12)
+		drm_plane_enable_fb_damage_clips(&cursor->base);
+
+	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
+
+	return cursor;
+
+fail:
+	intel_plane_free(cursor);
+
+	return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 79d7479beed2..722a1cf61941 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -137,16 +137,6 @@ static const u64 i9xx_format_modifiers[] = {
 	DRM_FORMAT_MOD_INVALID
 };
 
-/* Cursor formats */
-static const u32 intel_cursor_formats[] = {
-	DRM_FORMAT_ARGB8888,
-};
-
-static const u64 cursor_format_modifiers[] = {
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
-};
-
 static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
 				struct intel_crtc_state *pipe_config);
 static void ilk_pch_clock_get(struct intel_crtc *crtc,
@@ -2528,9 +2518,9 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,
 	return offset_aligned;
 }
 
-static u32 intel_plane_compute_aligned_offset(int *x, int *y,
-					      const struct intel_plane_state *state,
-					      int color_plane)
+u32 intel_plane_compute_aligned_offset(int *x, int *y,
+				       const struct intel_plane_state *state,
+				       int color_plane)
 {
 	struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane);
 	struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
@@ -3267,7 +3257,7 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)
 	}
 }
 
-static int
+int
 intel_plane_compute_gtt(struct intel_plane_state *plane_state)
 {
 	const struct intel_framebuffer *fb =
@@ -11536,569 +11526,6 @@ static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state)
 	return true;
 }
 
-static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv =
-		to_i915(plane_state->uapi.plane->dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-	u32 base;
-
-	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
-		base = sg_dma_address(obj->mm.pages->sgl);
-	else
-		base = intel_plane_ggtt_offset(plane_state);
-
-	return base + plane_state->color_plane[0].offset;
-}
-
-static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
-{
-	int x = plane_state->uapi.dst.x1;
-	int y = plane_state->uapi.dst.y1;
-	u32 pos = 0;
-
-	if (x < 0) {
-		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
-		x = -x;
-	}
-	pos |= x << CURSOR_X_SHIFT;
-
-	if (y < 0) {
-		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
-		y = -y;
-	}
-	pos |= y << CURSOR_Y_SHIFT;
-
-	return pos;
-}
-
-static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
-{
-	const struct drm_mode_config *config =
-		&plane_state->uapi.plane->dev->mode_config;
-	int width = drm_rect_width(&plane_state->uapi.dst);
-	int height = drm_rect_height(&plane_state->uapi.dst);
-
-	return width > 0 && width <= config->cursor_width &&
-		height > 0 && height <= config->cursor_height;
-}
-
-static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv =
-		to_i915(plane_state->uapi.plane->dev);
-	unsigned int rotation = plane_state->hw.rotation;
-	int src_x, src_y;
-	u32 offset;
-	int ret;
-
-	ret = intel_plane_compute_gtt(plane_state);
-	if (ret)
-		return ret;
-
-	if (!plane_state->uapi.visible)
-		return 0;
-
-	src_x = plane_state->uapi.src.x1 >> 16;
-	src_y = plane_state->uapi.src.y1 >> 16;
-
-	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
-	offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
-						    plane_state, 0);
-
-	if (src_x != 0 || src_y != 0) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "Arbitrary cursor panning not supported\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Put the final coordinates back so that the src
-	 * coordinate checks will see the right values.
-	 */
-	drm_rect_translate_to(&plane_state->uapi.src,
-			      src_x << 16, src_y << 16);
-
-	/* ILK+ do this automagically in hardware */
-	if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
-		const struct drm_framebuffer *fb = plane_state->hw.fb;
-		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
-		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
-
-		offset += (src_h * src_w - 1) * fb->format->cpp[0];
-	}
-
-	plane_state->color_plane[0].offset = offset;
-	plane_state->color_plane[0].x = src_x;
-	plane_state->color_plane[0].y = src_y;
-
-	return 0;
-}
-
-static int intel_check_cursor(struct intel_crtc_state *crtc_state,
-			      struct intel_plane_state *plane_state)
-{
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
-	const struct drm_rect src = plane_state->uapi.src;
-	const struct drm_rect dst = plane_state->uapi.dst;
-	int ret;
-
-	if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
-		drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
-		return -EINVAL;
-	}
-
-	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
-						DRM_PLANE_HELPER_NO_SCALING,
-						DRM_PLANE_HELPER_NO_SCALING,
-						true);
-	if (ret)
-		return ret;
-
-	/* Use the unclipped src/dst rectangles, which we program to hw */
-	plane_state->uapi.src = src;
-	plane_state->uapi.dst = dst;
-
-	ret = intel_cursor_check_surface(plane_state);
-	if (ret)
-		return ret;
-
-	if (!plane_state->uapi.visible)
-		return 0;
-
-	ret = intel_plane_check_src_coordinates(plane_state);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static unsigned int
-i845_cursor_max_stride(struct intel_plane *plane,
-		       u32 pixel_format, u64 modifier,
-		       unsigned int rotation)
-{
-	return 2048;
-}
-
-static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
-{
-	u32 cntl = 0;
-
-	if (crtc_state->gamma_enable)
-		cntl |= CURSOR_GAMMA_ENABLE;
-
-	return cntl;
-}
-
-static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
-			   const struct intel_plane_state *plane_state)
-{
-	return CURSOR_ENABLE |
-		CURSOR_FORMAT_ARGB |
-		CURSOR_STRIDE(plane_state->color_plane[0].stride);
-}
-
-static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
-{
-	int width = drm_rect_width(&plane_state->uapi.dst);
-
-	/*
-	 * 845g/865g are only limited by the width of their cursors,
-	 * the height is arbitrary up to the precision of the register.
-	 */
-	return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
-}
-
-static int i845_check_cursor(struct intel_crtc_state *crtc_state,
-			     struct intel_plane_state *plane_state)
-{
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
-	int ret;
-
-	ret = intel_check_cursor(crtc_state, plane_state);
-	if (ret)
-		return ret;
-
-	/* if we want to turn off the cursor ignore width and height */
-	if (!fb)
-		return 0;
-
-	/* Check for which cursor types we support */
-	if (!i845_cursor_size_ok(plane_state)) {
-		drm_dbg_kms(&i915->drm,
-			    "Cursor dimension %dx%d not supported\n",
-			    drm_rect_width(&plane_state->uapi.dst),
-			    drm_rect_height(&plane_state->uapi.dst));
-		return -EINVAL;
-	}
-
-	drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
-		    plane_state->color_plane[0].stride != fb->pitches[0]);
-
-	switch (fb->pitches[0]) {
-	case 256:
-	case 512:
-	case 1024:
-	case 2048:
-		break;
-	default:
-		 drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
-			     fb->pitches[0]);
-		return -EINVAL;
-	}
-
-	plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
-
-	return 0;
-}
-
-static void i845_update_cursor(struct intel_plane *plane,
-			       const struct intel_crtc_state *crtc_state,
-			       const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	u32 cntl = 0, base = 0, pos = 0, size = 0;
-	unsigned long irqflags;
-
-	if (plane_state && plane_state->uapi.visible) {
-		unsigned int width = drm_rect_width(&plane_state->uapi.dst);
-		unsigned int height = drm_rect_height(&plane_state->uapi.dst);
-
-		cntl = plane_state->ctl |
-			i845_cursor_ctl_crtc(crtc_state);
-
-		size = (height << 12) | width;
-
-		base = intel_cursor_base(plane_state);
-		pos = intel_cursor_position(plane_state);
-	}
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	/* On these chipsets we can only modify the base/size/stride
-	 * whilst the cursor is disabled.
-	 */
-	if (plane->cursor.base != base ||
-	    plane->cursor.size != size ||
-	    plane->cursor.cntl != cntl) {
-		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
-		intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
-		intel_de_write_fw(dev_priv, CURSIZE, size);
-		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
-		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
-
-		plane->cursor.base = base;
-		plane->cursor.size = size;
-		plane->cursor.cntl = cntl;
-	} else {
-		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
-	}
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static void i845_disable_cursor(struct intel_plane *plane,
-				const struct intel_crtc_state *crtc_state)
-{
-	i845_update_cursor(plane, crtc_state, NULL);
-}
-
-static bool i845_cursor_get_hw_state(struct intel_plane *plane,
-				     enum pipe *pipe)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum intel_display_power_domain power_domain;
-	intel_wakeref_t wakeref;
-	bool ret;
-
-	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
-	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
-	if (!wakeref)
-		return false;
-
-	ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
-
-	*pipe = PIPE_A;
-
-	intel_display_power_put(dev_priv, power_domain, wakeref);
-
-	return ret;
-}
-
-static unsigned int
-i9xx_cursor_max_stride(struct intel_plane *plane,
-		       u32 pixel_format, u64 modifier,
-		       unsigned int rotation)
-{
-	return plane->base.dev->mode_config.cursor_width * 4;
-}
-
-static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	u32 cntl = 0;
-
-	if (INTEL_GEN(dev_priv) >= 11)
-		return cntl;
-
-	if (crtc_state->gamma_enable)
-		cntl = MCURSOR_GAMMA_ENABLE;
-
-	if (crtc_state->csc_enable)
-		cntl |= MCURSOR_PIPE_CSC_ENABLE;
-
-	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
-		cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
-
-	return cntl;
-}
-
-static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
-			   const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv =
-		to_i915(plane_state->uapi.plane->dev);
-	u32 cntl = 0;
-
-	if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
-		cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
-
-	switch (drm_rect_width(&plane_state->uapi.dst)) {
-	case 64:
-		cntl |= MCURSOR_MODE_64_ARGB_AX;
-		break;
-	case 128:
-		cntl |= MCURSOR_MODE_128_ARGB_AX;
-		break;
-	case 256:
-		cntl |= MCURSOR_MODE_256_ARGB_AX;
-		break;
-	default:
-		MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
-		return 0;
-	}
-
-	if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
-		cntl |= MCURSOR_ROTATE_180;
-
-	return cntl;
-}
-
-static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv =
-		to_i915(plane_state->uapi.plane->dev);
-	int width = drm_rect_width(&plane_state->uapi.dst);
-	int height = drm_rect_height(&plane_state->uapi.dst);
-
-	if (!intel_cursor_size_ok(plane_state))
-		return false;
-
-	/* Cursor width is limited to a few power-of-two sizes */
-	switch (width) {
-	case 256:
-	case 128:
-	case 64:
-		break;
-	default:
-		return false;
-	}
-
-	/*
-	 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
-	 * height from 8 lines up to the cursor width, when the
-	 * cursor is not rotated. Everything else requires square
-	 * cursors.
-	 */
-	if (HAS_CUR_FBC(dev_priv) &&
-	    plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
-		if (height < 8 || height > width)
-			return false;
-	} else {
-		if (height != width)
-			return false;
-	}
-
-	return true;
-}
-
-static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
-			     struct intel_plane_state *plane_state)
-{
-	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	enum pipe pipe = plane->pipe;
-	int ret;
-
-	ret = intel_check_cursor(crtc_state, plane_state);
-	if (ret)
-		return ret;
-
-	/* if we want to turn off the cursor ignore width and height */
-	if (!fb)
-		return 0;
-
-	/* Check for which cursor types we support */
-	if (!i9xx_cursor_size_ok(plane_state)) {
-		drm_dbg(&dev_priv->drm,
-			"Cursor dimension %dx%d not supported\n",
-			drm_rect_width(&plane_state->uapi.dst),
-			drm_rect_height(&plane_state->uapi.dst));
-		return -EINVAL;
-	}
-
-	drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
-		    plane_state->color_plane[0].stride != fb->pitches[0]);
-
-	if (fb->pitches[0] !=
-	    drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "Invalid cursor stride (%u) (cursor width %d)\n",
-			    fb->pitches[0],
-			    drm_rect_width(&plane_state->uapi.dst));
-		return -EINVAL;
-	}
-
-	/*
-	 * There's something wrong with the cursor on CHV pipe C.
-	 * If it straddles the left edge of the screen then
-	 * moving it away from the edge or disabling it often
-	 * results in a pipe underrun, and often that can lead to
-	 * dead pipe (constant underrun reported, and it scans
-	 * out just a solid color). To recover from that, the
-	 * display power well must be turned off and on again.
-	 * Refuse the put the cursor into that compromised position.
-	 */
-	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
-	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "CHV cursor C not allowed to straddle the left screen edge\n");
-		return -EINVAL;
-	}
-
-	plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
-
-	return 0;
-}
-
-static void i9xx_update_cursor(struct intel_plane *plane,
-			       const struct intel_crtc_state *crtc_state,
-			       const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum pipe pipe = plane->pipe;
-	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
-	unsigned long irqflags;
-
-	if (plane_state && plane_state->uapi.visible) {
-		unsigned width = drm_rect_width(&plane_state->uapi.dst);
-		unsigned height = drm_rect_height(&plane_state->uapi.dst);
-
-		cntl = plane_state->ctl |
-			i9xx_cursor_ctl_crtc(crtc_state);
-
-		if (width != height)
-			fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
-
-		base = intel_cursor_base(plane_state);
-		pos = intel_cursor_position(plane_state);
-	}
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	/*
-	 * On some platforms writing CURCNTR first will also
-	 * cause CURPOS to be armed by the CURBASE write.
-	 * Without the CURCNTR write the CURPOS write would
-	 * arm itself. Thus we always update CURCNTR before
-	 * CURPOS.
-	 *
-	 * On other platforms CURPOS always requires the
-	 * CURBASE write to arm the update. Additonally
-	 * a write to any of the cursor register will cancel
-	 * an already armed cursor update. Thus leaving out
-	 * the CURBASE write after CURPOS could lead to a
-	 * cursor that doesn't appear to move, or even change
-	 * shape. Thus we always write CURBASE.
-	 *
-	 * The other registers are armed by by the CURBASE write
-	 * except when the plane is getting enabled at which time
-	 * the CURCNTR write arms the update.
-	 */
-
-	if (INTEL_GEN(dev_priv) >= 9)
-		skl_write_cursor_wm(plane, crtc_state);
-
-	if (!intel_crtc_needs_modeset(crtc_state))
-		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
-
-	if (plane->cursor.base != base ||
-	    plane->cursor.size != fbc_ctl ||
-	    plane->cursor.cntl != cntl) {
-		if (HAS_CUR_FBC(dev_priv))
-			intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
-					  fbc_ctl);
-		intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
-		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
-		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
-
-		plane->cursor.base = base;
-		plane->cursor.size = fbc_ctl;
-		plane->cursor.cntl = cntl;
-	} else {
-		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
-		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
-	}
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static void i9xx_disable_cursor(struct intel_plane *plane,
-				const struct intel_crtc_state *crtc_state)
-{
-	i9xx_update_cursor(plane, crtc_state, NULL);
-}
-
-static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
-				     enum pipe *pipe)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum intel_display_power_domain power_domain;
-	intel_wakeref_t wakeref;
-	bool ret;
-	u32 val;
-
-	/*
-	 * Not 100% correct for planes that can move between pipes,
-	 * but that's only the case for gen2-3 which don't have any
-	 * display power wells.
-	 */
-	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
-	if (!wakeref)
-		return false;
-
-	val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
-
-	ret = val & MCURSOR_MODE;
-
-	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-		*pipe = plane->pipe;
-	else
-		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
-			MCURSOR_PIPE_SELECT_SHIFT;
-
-	intel_display_power_put(dev_priv, power_domain, wakeref);
-
-	return ret;
-}
-
 /* VESA 640x480x72Hz mode to set on the pipe */
 static const struct drm_display_mode load_detect_mode = {
 	DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
@@ -16609,7 +16036,7 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc,
 	add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
 }
 
-static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
+int intel_plane_pin_fb(struct intel_plane_state *plane_state)
 {
 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
@@ -16639,7 +16066,7 @@ static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
 	return 0;
 }
 
-static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
+void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
 {
 	struct i915_vma *vma;
 
@@ -16875,13 +16302,6 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
 	}
 }
 
-static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
-					      u32 format, u64 modifier)
-{
-	return modifier == DRM_FORMAT_MOD_LINEAR &&
-		format == DRM_FORMAT_ARGB8888;
-}
-
 static const struct drm_plane_funcs i965_plane_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
 	.disable_plane = drm_atomic_helper_disable_plane,
@@ -16900,142 +16320,6 @@ static const struct drm_plane_funcs i8xx_plane_funcs = {
 	.format_mod_supported = i8xx_plane_format_mod_supported,
 };
 
-static int
-intel_legacy_cursor_update(struct drm_plane *_plane,
-			   struct drm_crtc *_crtc,
-			   struct drm_framebuffer *fb,
-			   int crtc_x, int crtc_y,
-			   unsigned int crtc_w, unsigned int crtc_h,
-			   u32 src_x, u32 src_y,
-			   u32 src_w, u32 src_h,
-			   struct drm_modeset_acquire_ctx *ctx)
-{
-	struct intel_plane *plane = to_intel_plane(_plane);
-	struct intel_crtc *crtc = to_intel_crtc(_crtc);
-	struct intel_plane_state *old_plane_state =
-		to_intel_plane_state(plane->base.state);
-	struct intel_plane_state *new_plane_state;
-	struct intel_crtc_state *crtc_state =
-		to_intel_crtc_state(crtc->base.state);
-	struct intel_crtc_state *new_crtc_state;
-	int ret;
-
-	/*
-	 * When crtc is inactive or there is a modeset pending,
-	 * wait for it to complete in the slowpath
-	 *
-	 * FIXME bigjoiner fastpath would be good
-	 */
-	if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
-	    crtc_state->update_pipe || crtc_state->bigjoiner)
-		goto slow;
-
-	/*
-	 * Don't do an async update if there is an outstanding commit modifying
-	 * the plane.  This prevents our async update's changes from getting
-	 * overridden by a previous synchronous update's state.
-	 */
-	if (old_plane_state->uapi.commit &&
-	    !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
-		goto slow;
-
-	/*
-	 * If any parameters change that may affect watermarks,
-	 * take the slowpath. Only changing fb or position should be
-	 * in the fastpath.
-	 */
-	if (old_plane_state->uapi.crtc != &crtc->base ||
-	    old_plane_state->uapi.src_w != src_w ||
-	    old_plane_state->uapi.src_h != src_h ||
-	    old_plane_state->uapi.crtc_w != crtc_w ||
-	    old_plane_state->uapi.crtc_h != crtc_h ||
-	    !old_plane_state->uapi.fb != !fb)
-		goto slow;
-
-	new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
-	if (!new_plane_state)
-		return -ENOMEM;
-
-	new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
-	if (!new_crtc_state) {
-		ret = -ENOMEM;
-		goto out_free;
-	}
-
-	drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
-
-	new_plane_state->uapi.src_x = src_x;
-	new_plane_state->uapi.src_y = src_y;
-	new_plane_state->uapi.src_w = src_w;
-	new_plane_state->uapi.src_h = src_h;
-	new_plane_state->uapi.crtc_x = crtc_x;
-	new_plane_state->uapi.crtc_y = crtc_y;
-	new_plane_state->uapi.crtc_w = crtc_w;
-	new_plane_state->uapi.crtc_h = crtc_h;
-
-	intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
-
-	ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
-						  old_plane_state, new_plane_state);
-	if (ret)
-		goto out_free;
-
-	ret = intel_plane_pin_fb(new_plane_state);
-	if (ret)
-		goto out_free;
-
-	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
-				ORIGIN_FLIP);
-	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
-				to_intel_frontbuffer(new_plane_state->hw.fb),
-				plane->frontbuffer_bit);
-
-	/* Swap plane state */
-	plane->base.state = &new_plane_state->uapi;
-
-	/*
-	 * We cannot swap crtc_state as it may be in use by an atomic commit or
-	 * page flip that's running simultaneously. If we swap crtc_state and
-	 * destroy the old state, we will cause a use-after-free there.
-	 *
-	 * Only update active_planes, which is needed for our internal
-	 * bookkeeping. Either value will do the right thing when updating
-	 * planes atomically. If the cursor was part of the atomic update then
-	 * we would have taken the slowpath.
-	 */
-	crtc_state->active_planes = new_crtc_state->active_planes;
-
-	if (new_plane_state->uapi.visible)
-		intel_update_plane(plane, crtc_state, new_plane_state);
-	else
-		intel_disable_plane(plane, crtc_state);
-
-	intel_plane_unpin_fb(old_plane_state);
-
-out_free:
-	if (new_crtc_state)
-		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
-	if (ret)
-		intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
-	else
-		intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
-	return ret;
-
-slow:
-	return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
-					      crtc_x, crtc_y, crtc_w, crtc_h,
-					      src_x, src_y, src_w, src_h, ctx);
-}
-
-static const struct drm_plane_funcs intel_cursor_plane_funcs = {
-	.update_plane = intel_legacy_cursor_update,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = intel_plane_destroy,
-	.atomic_duplicate_state = intel_plane_duplicate_state,
-	.atomic_destroy_state = intel_plane_destroy_state,
-	.format_mod_supported = intel_cursor_format_mod_supported,
-};
-
 static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
 			       enum i9xx_plane_id i9xx_plane)
 {
@@ -17187,74 +16471,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 	return ERR_PTR(ret);
 }
 
-static struct intel_plane *
-intel_cursor_plane_create(struct drm_i915_private *dev_priv,
-			  enum pipe pipe)
-{
-	struct intel_plane *cursor;
-	int ret, zpos;
-
-	cursor = intel_plane_alloc();
-	if (IS_ERR(cursor))
-		return cursor;
-
-	cursor->pipe = pipe;
-	cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
-	cursor->id = PLANE_CURSOR;
-	cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
-
-	if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
-		cursor->max_stride = i845_cursor_max_stride;
-		cursor->update_plane = i845_update_cursor;
-		cursor->disable_plane = i845_disable_cursor;
-		cursor->get_hw_state = i845_cursor_get_hw_state;
-		cursor->check_plane = i845_check_cursor;
-	} else {
-		cursor->max_stride = i9xx_cursor_max_stride;
-		cursor->update_plane = i9xx_update_cursor;
-		cursor->disable_plane = i9xx_disable_cursor;
-		cursor->get_hw_state = i9xx_cursor_get_hw_state;
-		cursor->check_plane = i9xx_check_cursor;
-	}
-
-	cursor->cursor.base = ~0;
-	cursor->cursor.cntl = ~0;
-
-	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
-		cursor->cursor.size = ~0;
-
-	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
-				       0, &intel_cursor_plane_funcs,
-				       intel_cursor_formats,
-				       ARRAY_SIZE(intel_cursor_formats),
-				       cursor_format_modifiers,
-				       DRM_PLANE_TYPE_CURSOR,
-				       "cursor %c", pipe_name(pipe));
-	if (ret)
-		goto fail;
-
-	if (INTEL_GEN(dev_priv) >= 4)
-		drm_plane_create_rotation_property(&cursor->base,
-						   DRM_MODE_ROTATE_0,
-						   DRM_MODE_ROTATE_0 |
-						   DRM_MODE_ROTATE_180);
-
-	zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
-	drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
-
-	if (INTEL_GEN(dev_priv) >= 12)
-		drm_plane_enable_fb_damage_clips(&cursor->base);
-
-	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
-
-	return cursor;
-
-fail:
-	intel_plane_free(cursor);
-
-	return ERR_PTR(ret);
-}
-
 static int intel_crtc_late_register(struct drm_crtc *crtc)
 {
 	intel_crtc_debugfs_add(crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index a5771bfecba6..f0a5bf69656f 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -647,6 +647,18 @@ bool
 intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
 				    uint64_t modifier);
 
+int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
+u32 intel_plane_compute_aligned_offset(int *x, int *y,
+				       const struct intel_plane_state *state,
+				       int color_plane);
+int intel_plane_pin_fb(struct intel_plane_state *plane_state);
+void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
+
+/* cursor */
+struct intel_plane *
+intel_cursor_plane_create(struct drm_i915_private *dev_priv,
+			  enum pipe pipe);
+
 /* modesetting */
 void intel_modeset_init_hw(struct drm_i915_private *i915);
 int intel_modeset_init_noirq(struct drm_i915_private *i915);
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 5/9] drm/i915: refactor some crtc code out of intel display.
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (3 preceding siblings ...)
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10 15:13   ` Ville Syrjälä
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 6/9] drm/i915: refactor pll code out into intel_dpll_legacy.c Dave Airlie
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

There may be more crtc code that can be pulled out, but this
is a good start.

RFC: maybe call the new file something different

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/Makefile                |   1 +
 drivers/gpu/drm/i915/display/intel_crtc.c    | 951 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_display.c | 932 ------------------
 drivers/gpu/drm/i915/display/intel_display.h |   7 +
 4 files changed, 959 insertions(+), 932 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_crtc.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 98a35b939052..ffec257702af 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -196,6 +196,7 @@ i915-y += \
 	display/intel_color.o \
 	display/intel_combo_phy.o \
 	display/intel_connector.o \
+	display/intel_crtc.o \
 	display/intel_csr.o \
 	display/intel_cursor.o \
 	display/intel_display.o \
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
new file mode 100644
index 000000000000..75a79f18cee2
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -0,0 +1,951 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_plane_helper.h>
+
+#include "intel_atomic.h"
+#include "intel_atomic_plane.h"
+#include "intel_color.h"
+#include "intel_display_debugfs.h"
+#include "intel_display_types.h"
+#include "intel_pipe_crc.h"
+#include "intel_sprite.h"
+
+/* Primary plane formats for gen <= 3 */
+static const u32 i8xx_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+};
+
+/* Primary plane formats for ivb (no fp16 due to hw issue) */
+static const u32 ivb_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+};
+
+/* Primary plane formats for gen >= 4, except ivb */
+static const u32 i965_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_XBGR16161616F,
+};
+
+/* Primary plane formats for vlv/chv */
+static const u32 vlv_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_XBGR16161616F,
+};
+
+static const u64 i9xx_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
+					    u32 format, u64 modifier)
+{
+	switch (modifier) {
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+		break;
+	default:
+		return false;
+	}
+
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XRGB8888:
+		return modifier == DRM_FORMAT_MOD_LINEAR ||
+			modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
+					    u32 format, u64 modifier)
+{
+	switch (modifier) {
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+		break;
+	default:
+		return false;
+	}
+
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_XBGR16161616F:
+		return modifier == DRM_FORMAT_MOD_LINEAR ||
+			modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
+			       enum i9xx_plane_id i9xx_plane)
+{
+	if (!HAS_FBC(dev_priv))
+		return false;
+
+	if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
+		return i9xx_plane == PLANE_A; /* tied to pipe A */
+	else if (IS_IVYBRIDGE(dev_priv))
+		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
+			i9xx_plane == PLANE_C;
+	else if (INTEL_GEN(dev_priv) >= 4)
+		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
+	else
+		return i9xx_plane == PLANE_A;
+}
+
+static void assert_vblank_disabled(struct drm_crtc *crtc)
+{
+	if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
+		drm_crtc_vblank_put(crtc);
+}
+
+u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
+
+	if (!vblank->max_vblank_count)
+		return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
+
+	return crtc->base.funcs->get_vblank_counter(&crtc->base);
+}
+
+u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	u32 mode_flags = crtc->mode_flags;
+
+	/*
+	 * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
+	 * have updated at the beginning of TE, if we want to use
+	 * the hw counter, then we would find it updated in only
+	 * the next TE, hence switching to sw counter.
+	 */
+	if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
+		return 0;
+
+	/*
+	 * On i965gm the hardware frame counter reads
+	 * zero when the TV encoder is enabled :(
+	 */
+	if (IS_I965GM(dev_priv) &&
+	    (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
+		return 0;
+
+	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		return 0xffffffff; /* full 32 bit counter */
+	else if (INTEL_GEN(dev_priv) >= 3)
+		return 0xffffff; /* only 24 bits of frame count */
+	else
+		return 0; /* Gen2 doesn't have a hardware frame counter */
+}
+
+void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	assert_vblank_disabled(&crtc->base);
+	drm_crtc_set_max_vblank_count(&crtc->base,
+				      intel_crtc_max_vblank_count(crtc_state));
+	drm_crtc_vblank_on(&crtc->base);
+}
+
+void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	drm_crtc_vblank_off(&crtc->base);
+	assert_vblank_disabled(&crtc->base);
+}
+
+struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
+{
+	struct intel_crtc_state *crtc_state;
+
+	crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
+
+	if (crtc_state)
+		intel_crtc_state_reset(crtc_state, crtc);
+
+	return crtc_state;
+}
+
+void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
+			    struct intel_crtc *crtc)
+{
+	memset(crtc_state, 0, sizeof(*crtc_state));
+
+	__drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
+
+	crtc_state->cpu_transcoder = INVALID_TRANSCODER;
+	crtc_state->master_transcoder = INVALID_TRANSCODER;
+	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
+	crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
+	crtc_state->scaler_state.scaler_id = -1;
+	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
+}
+
+static bool i9xx_plane_has_windowing(struct intel_plane *plane)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+
+	if (IS_CHERRYVIEW(dev_priv))
+		return i9xx_plane == PLANE_B;
+	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		return false;
+	else if (IS_GEN(dev_priv, 4))
+		return i9xx_plane == PLANE_C;
+	else
+		return i9xx_plane == PLANE_B ||
+			i9xx_plane == PLANE_C;
+}
+
+static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
+			  const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->uapi.plane->dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	unsigned int rotation = plane_state->hw.rotation;
+	u32 dspcntr;
+
+	dspcntr = DISPLAY_PLANE_ENABLE;
+
+	if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
+	    IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
+		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
+	switch (fb->format->format) {
+	case DRM_FORMAT_C8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case DRM_FORMAT_XRGB1555:
+		dspcntr |= DISPPLANE_BGRX555;
+		break;
+	case DRM_FORMAT_ARGB1555:
+		dspcntr |= DISPPLANE_BGRA555;
+		break;
+	case DRM_FORMAT_RGB565:
+		dspcntr |= DISPPLANE_BGRX565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+		dspcntr |= DISPPLANE_BGRX888;
+		break;
+	case DRM_FORMAT_XBGR8888:
+		dspcntr |= DISPPLANE_RGBX888;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		dspcntr |= DISPPLANE_BGRA888;
+		break;
+	case DRM_FORMAT_ABGR8888:
+		dspcntr |= DISPPLANE_RGBA888;
+		break;
+	case DRM_FORMAT_XRGB2101010:
+		dspcntr |= DISPPLANE_BGRX101010;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+		dspcntr |= DISPPLANE_RGBX101010;
+		break;
+	case DRM_FORMAT_ARGB2101010:
+		dspcntr |= DISPPLANE_BGRA101010;
+		break;
+	case DRM_FORMAT_ABGR2101010:
+		dspcntr |= DISPPLANE_RGBA101010;
+		break;
+	case DRM_FORMAT_XBGR16161616F:
+		dspcntr |= DISPPLANE_RGBX161616;
+		break;
+	default:
+		MISSING_CASE(fb->format->format);
+		return 0;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 4 &&
+	    fb->modifier == I915_FORMAT_MOD_X_TILED)
+		dspcntr |= DISPPLANE_TILED;
+
+	if (rotation & DRM_MODE_ROTATE_180)
+		dspcntr |= DISPPLANE_ROTATE_180;
+
+	if (rotation & DRM_MODE_REFLECT_X)
+		dspcntr |= DISPPLANE_MIRROR;
+
+	return dspcntr;
+}
+
+static int
+i9xx_plane_check(struct intel_crtc_state *crtc_state,
+		 struct intel_plane_state *plane_state)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+	int ret;
+
+	ret = chv_plane_check_rotation(plane_state);
+	if (ret)
+		return ret;
+
+	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
+						DRM_PLANE_HELPER_NO_SCALING,
+						DRM_PLANE_HELPER_NO_SCALING,
+						i9xx_plane_has_windowing(plane));
+	if (ret)
+		return ret;
+
+	ret = i9xx_check_plane_surface(plane_state);
+	if (ret)
+		return ret;
+
+	if (!plane_state->uapi.visible)
+		return 0;
+
+	ret = intel_plane_check_src_coordinates(plane_state);
+	if (ret)
+		return ret;
+
+	plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
+
+	return 0;
+}
+
+static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	u32 dspcntr = 0;
+
+	if (crtc_state->gamma_enable)
+		dspcntr |= DISPPLANE_GAMMA_ENABLE;
+
+	if (crtc_state->csc_enable)
+		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
+
+	if (INTEL_GEN(dev_priv) < 5)
+		dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
+
+	return dspcntr;
+}
+
+static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
+			     const struct intel_plane_state *plane_state,
+			     unsigned int *num, unsigned int *den)
+{
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	unsigned int cpp = fb->format->cpp[0];
+
+	/*
+	 * g4x bspec says 64bpp pixel rate can't exceed 80%
+	 * of cdclk when the sprite plane is enabled on the
+	 * same pipe. ilk/snb bspec says 64bpp pixel rate is
+	 * never allowed to exceed 80% of cdclk. Let's just go
+	 * with the ilk/snb limit always.
+	 */
+	if (cpp == 8) {
+		*num = 10;
+		*den = 8;
+	} else {
+		*num = 1;
+		*den = 1;
+	}
+}
+
+static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
+				const struct intel_plane_state *plane_state)
+{
+	unsigned int pixel_rate;
+	unsigned int num, den;
+
+	/*
+	 * Note that crtc_state->pixel_rate accounts for both
+	 * horizontal and vertical panel fitter downscaling factors.
+	 * Pre-HSW bspec tells us to only consider the horizontal
+	 * downscaling factor here. We ignore that and just consider
+	 * both for simplicity.
+	 */
+	pixel_rate = crtc_state->pixel_rate;
+
+	i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
+
+	/* two pixels per clock with double wide pipe */
+	if (crtc_state->double_wide)
+		den *= 2;
+
+	return DIV_ROUND_UP(pixel_rate * num, den);
+}
+
+static void i9xx_update_plane(struct intel_plane *plane,
+			      const struct intel_crtc_state *crtc_state,
+			      const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+	u32 linear_offset;
+	int x = plane_state->color_plane[0].x;
+	int y = plane_state->color_plane[0].y;
+	int crtc_x = plane_state->uapi.dst.x1;
+	int crtc_y = plane_state->uapi.dst.y1;
+	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
+	int crtc_h = drm_rect_height(&plane_state->uapi.dst);
+	unsigned long irqflags;
+	u32 dspaddr_offset;
+	u32 dspcntr;
+
+	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
+
+	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		dspaddr_offset = plane_state->color_plane[0].offset;
+	else
+		dspaddr_offset = linear_offset;
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
+			  plane_state->color_plane[0].stride);
+
+	if (INTEL_GEN(dev_priv) < 4) {
+		/*
+		 * PLANE_A doesn't actually have a full window
+		 * generator but let's assume we still need to
+		 * program whatever is there.
+		 */
+		intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
+				  (crtc_y << 16) | crtc_x);
+		intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
+				  ((crtc_h - 1) << 16) | (crtc_w - 1));
+	} else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
+		intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
+				  (crtc_y << 16) | crtc_x);
+		intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
+				  ((crtc_h - 1) << 16) | (crtc_w - 1));
+		intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
+	}
+
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
+		intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
+				  (y << 16) | x);
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
+				  linear_offset);
+		intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
+				  (y << 16) | x);
+	}
+
+	/*
+	 * The control register self-arms if the plane was previously
+	 * disabled. Try to make the plane enable atomic by writing
+	 * the control register just before the surface register.
+	 */
+	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
+	if (INTEL_GEN(dev_priv) >= 4)
+		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
+				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
+	else
+		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
+				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static void i9xx_disable_plane(struct intel_plane *plane,
+			       const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+	unsigned long irqflags;
+	u32 dspcntr;
+
+	/*
+	 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
+	 * enable on ilk+ affect the pipe bottom color as
+	 * well, so we must configure them even if the plane
+	 * is disabled.
+	 *
+	 * On pre-g4x there is no way to gamma correct the
+	 * pipe bottom color but we'll keep on doing this
+	 * anyway so that the crtc state readout works correctly.
+	 */
+	dspcntr = i9xx_plane_ctl_crtc(crtc_state);
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
+	if (INTEL_GEN(dev_priv) >= 4)
+		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
+	else
+		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
+				    enum pipe *pipe)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum intel_display_power_domain power_domain;
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+	intel_wakeref_t wakeref;
+	bool ret;
+	u32 val;
+
+	/*
+	 * Not 100% correct for planes that can move between pipes,
+	 * but that's only the case for gen2-4 which don't have any
+	 * display power wells.
+	 */
+	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
+		return false;
+
+	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
+
+	ret = val & DISPLAY_PLANE_ENABLE;
+
+	if (INTEL_GEN(dev_priv) >= 5)
+		*pipe = plane->pipe;
+	else
+		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
+			DISPPLANE_SEL_PIPE_SHIFT;
+
+	intel_display_power_put(dev_priv, power_domain, wakeref);
+
+	return ret;
+}
+
+unsigned int
+i9xx_plane_max_stride(struct intel_plane *plane,
+		      u32 pixel_format, u64 modifier,
+		      unsigned int rotation)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+
+	if (!HAS_GMCH(dev_priv)) {
+		return 32*1024;
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		if (modifier == I915_FORMAT_MOD_X_TILED)
+			return 16*1024;
+		else
+			return 32*1024;
+	} else if (INTEL_GEN(dev_priv) >= 3) {
+		if (modifier == I915_FORMAT_MOD_X_TILED)
+			return 8*1024;
+		else
+			return 16*1024;
+	} else {
+		if (plane->i9xx_plane == PLANE_C)
+			return 4*1024;
+		else
+			return 8*1024;
+	}
+}
+
+static const struct drm_plane_funcs i965_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = intel_plane_destroy,
+	.atomic_duplicate_state = intel_plane_duplicate_state,
+	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = i965_plane_format_mod_supported,
+};
+
+static const struct drm_plane_funcs i8xx_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = intel_plane_destroy,
+	.atomic_duplicate_state = intel_plane_duplicate_state,
+	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = i8xx_plane_format_mod_supported,
+};
+
+static struct intel_plane *
+intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	struct intel_plane *plane;
+	const struct drm_plane_funcs *plane_funcs;
+	unsigned int supported_rotations;
+	const u32 *formats;
+	int num_formats;
+	int ret, zpos;
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		return skl_universal_plane_create(dev_priv, pipe,
+						  PLANE_PRIMARY);
+
+	plane = intel_plane_alloc();
+	if (IS_ERR(plane))
+		return plane;
+
+	plane->pipe = pipe;
+	/*
+	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
+	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
+	 */
+	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
+	    INTEL_NUM_PIPES(dev_priv) == 2)
+		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
+	else
+		plane->i9xx_plane = (enum i9xx_plane_id) pipe;
+	plane->id = PLANE_PRIMARY;
+	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
+
+	plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
+	if (plane->has_fbc) {
+		struct intel_fbc *fbc = &dev_priv->fbc;
+
+		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
+	}
+
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		formats = vlv_primary_formats;
+		num_formats = ARRAY_SIZE(vlv_primary_formats);
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		/*
+		 * WaFP16GammaEnabling:ivb
+		 * "Workaround : When using the 64-bit format, the plane
+		 *  output on each color channel has one quarter amplitude.
+		 *  It can be brought up to full amplitude by using pipe
+		 *  gamma correction or pipe color space conversion to
+		 *  multiply the plane output by four."
+		 *
+		 * There is no dedicated plane gamma for the primary plane,
+		 * and using the pipe gamma/csc could conflict with other
+		 * planes, so we choose not to expose fp16 on IVB primary
+		 * planes. HSW primary planes no longer have this problem.
+		 */
+		if (IS_IVYBRIDGE(dev_priv)) {
+			formats = ivb_primary_formats;
+			num_formats = ARRAY_SIZE(ivb_primary_formats);
+		} else {
+			formats = i965_primary_formats;
+			num_formats = ARRAY_SIZE(i965_primary_formats);
+		}
+	} else {
+		formats = i8xx_primary_formats;
+		num_formats = ARRAY_SIZE(i8xx_primary_formats);
+	}
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		plane_funcs = &i965_plane_funcs;
+	else
+		plane_funcs = &i8xx_plane_funcs;
+
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		plane->min_cdclk = vlv_plane_min_cdclk;
+	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
+		plane->min_cdclk = hsw_plane_min_cdclk;
+	else if (IS_IVYBRIDGE(dev_priv))
+		plane->min_cdclk = ivb_plane_min_cdclk;
+	else
+		plane->min_cdclk = i9xx_plane_min_cdclk;
+
+	plane->max_stride = i9xx_plane_max_stride;
+	plane->update_plane = i9xx_update_plane;
+	plane->disable_plane = i9xx_disable_plane;
+	plane->get_hw_state = i9xx_plane_get_hw_state;
+	plane->check_plane = i9xx_plane_check;
+
+	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
+					       0, plane_funcs,
+					       formats, num_formats,
+					       i9xx_format_modifiers,
+					       DRM_PLANE_TYPE_PRIMARY,
+					       "primary %c", pipe_name(pipe));
+	else
+		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
+					       0, plane_funcs,
+					       formats, num_formats,
+					       i9xx_format_modifiers,
+					       DRM_PLANE_TYPE_PRIMARY,
+					       "plane %c",
+					       plane_name(plane->i9xx_plane));
+	if (ret)
+		goto fail;
+
+	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+		supported_rotations =
+			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
+			DRM_MODE_REFLECT_X;
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		supported_rotations =
+			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
+	} else {
+		supported_rotations = DRM_MODE_ROTATE_0;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		drm_plane_create_rotation_property(&plane->base,
+						   DRM_MODE_ROTATE_0,
+						   supported_rotations);
+
+	zpos = 0;
+	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
+
+	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+
+	return plane;
+
+fail:
+	intel_plane_free(plane);
+
+	return ERR_PTR(ret);
+}
+
+static struct intel_crtc *intel_crtc_alloc(void)
+{
+	struct intel_crtc_state *crtc_state;
+	struct intel_crtc *crtc;
+
+	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
+	if (!crtc)
+		return ERR_PTR(-ENOMEM);
+
+	crtc_state = intel_crtc_state_alloc(crtc);
+	if (!crtc_state) {
+		kfree(crtc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	crtc->base.state = &crtc_state->uapi;
+	crtc->config = crtc_state;
+
+	return crtc;
+}
+
+static void intel_crtc_free(struct intel_crtc *crtc)
+{
+	intel_crtc_destroy_state(&crtc->base, crtc->base.state);
+	kfree(crtc);
+}
+
+static void intel_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	drm_crtc_cleanup(crtc);
+	kfree(intel_crtc);
+}
+
+static int intel_crtc_late_register(struct drm_crtc *crtc)
+{
+	intel_crtc_debugfs_add(crtc);
+	return 0;
+}
+
+#define INTEL_CRTC_FUNCS \
+	.gamma_set = drm_atomic_helper_legacy_gamma_set, \
+	.set_config = drm_atomic_helper_set_config, \
+	.destroy = intel_crtc_destroy, \
+	.page_flip = drm_atomic_helper_page_flip, \
+	.atomic_duplicate_state = intel_crtc_duplicate_state, \
+	.atomic_destroy_state = intel_crtc_destroy_state, \
+	.set_crc_source = intel_crtc_set_crc_source, \
+	.verify_crc_source = intel_crtc_verify_crc_source, \
+	.get_crc_sources = intel_crtc_get_crc_sources, \
+	.late_register = intel_crtc_late_register
+
+static const struct drm_crtc_funcs bdw_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = g4x_get_vblank_counter,
+	.enable_vblank = bdw_enable_vblank,
+	.disable_vblank = bdw_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs ilk_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = g4x_get_vblank_counter,
+	.enable_vblank = ilk_enable_vblank,
+	.disable_vblank = ilk_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs g4x_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = g4x_get_vblank_counter,
+	.enable_vblank = i965_enable_vblank,
+	.disable_vblank = i965_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i965_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = i915_get_vblank_counter,
+	.enable_vblank = i965_enable_vblank,
+	.disable_vblank = i965_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i915gm_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = i915_get_vblank_counter,
+	.enable_vblank = i915gm_enable_vblank,
+	.disable_vblank = i915gm_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i915_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = i915_get_vblank_counter,
+	.enable_vblank = i8xx_enable_vblank,
+	.disable_vblank = i8xx_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i8xx_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	/* no hw vblank counter */
+	.enable_vblank = i8xx_enable_vblank,
+	.disable_vblank = i8xx_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	struct intel_plane *primary, *cursor;
+	const struct drm_crtc_funcs *funcs;
+	struct intel_crtc *crtc;
+	int sprite, ret;
+
+	crtc = intel_crtc_alloc();
+	if (IS_ERR(crtc))
+		return PTR_ERR(crtc);
+
+	crtc->pipe = pipe;
+	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
+
+	primary = intel_primary_plane_create(dev_priv, pipe);
+	if (IS_ERR(primary)) {
+		ret = PTR_ERR(primary);
+		goto fail;
+	}
+	crtc->plane_ids_mask |= BIT(primary->id);
+
+	for_each_sprite(dev_priv, pipe, sprite) {
+		struct intel_plane *plane;
+
+		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
+		if (IS_ERR(plane)) {
+			ret = PTR_ERR(plane);
+			goto fail;
+		}
+		crtc->plane_ids_mask |= BIT(plane->id);
+	}
+
+	cursor = intel_cursor_plane_create(dev_priv, pipe);
+	if (IS_ERR(cursor)) {
+		ret = PTR_ERR(cursor);
+		goto fail;
+	}
+	crtc->plane_ids_mask |= BIT(cursor->id);
+
+	if (HAS_GMCH(dev_priv)) {
+		if (IS_CHERRYVIEW(dev_priv) ||
+		    IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
+			funcs = &g4x_crtc_funcs;
+		else if (IS_GEN(dev_priv, 4))
+			funcs = &i965_crtc_funcs;
+		else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
+			funcs = &i915gm_crtc_funcs;
+		else if (IS_GEN(dev_priv, 3))
+			funcs = &i915_crtc_funcs;
+		else
+			funcs = &i8xx_crtc_funcs;
+	} else {
+		if (INTEL_GEN(dev_priv) >= 8)
+			funcs = &bdw_crtc_funcs;
+		else
+			funcs = &ilk_crtc_funcs;
+	}
+
+	ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
+					&primary->base, &cursor->base,
+					funcs, "pipe %c", pipe_name(pipe));
+	if (ret)
+		goto fail;
+
+	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
+	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
+	dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
+
+	if (INTEL_GEN(dev_priv) < 9) {
+		enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
+
+		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
+		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
+		dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 10)
+		drm_crtc_create_scaling_filter_property(&crtc->base,
+						BIT(DRM_SCALING_FILTER_DEFAULT) |
+						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
+
+	intel_color_init(crtc);
+
+	intel_crtc_crc_init(crtc);
+
+	drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
+
+	return 0;
+
+fail:
+	intel_crtc_free(crtc);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 722a1cf61941..2507a72ee249 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -87,56 +87,6 @@
 #include "intel_tc.h"
 #include "intel_vga.h"
 
-/* Primary plane formats for gen <= 3 */
-static const u32 i8xx_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_XRGB1555,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-};
-
-/* Primary plane formats for ivb (no fp16 due to hw issue) */
-static const u32 ivb_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-};
-
-/* Primary plane formats for gen >= 4, except ivb */
-static const u32 i965_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_XBGR16161616F,
-};
-
-/* Primary plane formats for vlv/chv */
-static const u32 vlv_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_ARGB2101010,
-	DRM_FORMAT_ABGR2101010,
-	DRM_FORMAT_XBGR16161616F,
-};
-
-static const u64 i9xx_format_modifiers[] = {
-	I915_FORMAT_MOD_X_TILED,
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
-};
-
 static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
 				struct intel_crtc_state *pipe_config);
 static void ilk_pch_clock_get(struct intel_crtc *crtc,
@@ -162,7 +112,6 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state);
 static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
 static void intel_modeset_setup_hw_state(struct drm_device *dev,
 					 struct drm_modeset_acquire_ctx *ctx);
-static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
 
 struct intel_limit {
 	struct {
@@ -1301,12 +1250,6 @@ static void assert_planes_disabled(struct intel_crtc *crtc)
 		assert_plane_disabled(plane);
 }
 
-static void assert_vblank_disabled(struct drm_crtc *crtc)
-{
-	if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
-		drm_crtc_vblank_put(crtc);
-}
-
 void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
 				    enum pipe pipe)
 {
@@ -1791,55 +1734,6 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
 		return crtc->pipe;
 }
 
-static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	u32 mode_flags = crtc->mode_flags;
-
-	/*
-	 * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
-	 * have updated at the beginning of TE, if we want to use
-	 * the hw counter, then we would find it updated in only
-	 * the next TE, hence switching to sw counter.
-	 */
-	if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
-		return 0;
-
-	/*
-	 * On i965gm the hardware frame counter reads
-	 * zero when the TV encoder is enabled :(
-	 */
-	if (IS_I965GM(dev_priv) &&
-	    (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
-		return 0;
-
-	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-		return 0xffffffff; /* full 32 bit counter */
-	else if (INTEL_GEN(dev_priv) >= 3)
-		return 0xffffff; /* only 24 bits of frame count */
-	else
-		return 0; /* Gen2 doesn't have a hardware frame counter */
-}
-
-void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-	assert_vblank_disabled(&crtc->base);
-	drm_crtc_set_max_vblank_count(&crtc->base,
-				      intel_crtc_max_vblank_count(crtc_state));
-	drm_crtc_vblank_on(&crtc->base);
-}
-
-void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-	drm_crtc_vblank_off(&crtc->base);
-	assert_vblank_disabled(&crtc->base);
-}
-
 void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
@@ -4046,171 +3940,6 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
 	return 0;
 }
 
-static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
-			     const struct intel_plane_state *plane_state,
-			     unsigned int *num, unsigned int *den)
-{
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	unsigned int cpp = fb->format->cpp[0];
-
-	/*
-	 * g4x bspec says 64bpp pixel rate can't exceed 80%
-	 * of cdclk when the sprite plane is enabled on the
-	 * same pipe. ilk/snb bspec says 64bpp pixel rate is
-	 * never allowed to exceed 80% of cdclk. Let's just go
-	 * with the ilk/snb limit always.
-	 */
-	if (cpp == 8) {
-		*num = 10;
-		*den = 8;
-	} else {
-		*num = 1;
-		*den = 1;
-	}
-}
-
-static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
-				const struct intel_plane_state *plane_state)
-{
-	unsigned int pixel_rate;
-	unsigned int num, den;
-
-	/*
-	 * Note that crtc_state->pixel_rate accounts for both
-	 * horizontal and vertical panel fitter downscaling factors.
-	 * Pre-HSW bspec tells us to only consider the horizontal
-	 * downscaling factor here. We ignore that and just consider
-	 * both for simplicity.
-	 */
-	pixel_rate = crtc_state->pixel_rate;
-
-	i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
-
-	/* two pixels per clock with double wide pipe */
-	if (crtc_state->double_wide)
-		den *= 2;
-
-	return DIV_ROUND_UP(pixel_rate * num, den);
-}
-
-unsigned int
-i9xx_plane_max_stride(struct intel_plane *plane,
-		      u32 pixel_format, u64 modifier,
-		      unsigned int rotation)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-
-	if (!HAS_GMCH(dev_priv)) {
-		return 32*1024;
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		if (modifier == I915_FORMAT_MOD_X_TILED)
-			return 16*1024;
-		else
-			return 32*1024;
-	} else if (INTEL_GEN(dev_priv) >= 3) {
-		if (modifier == I915_FORMAT_MOD_X_TILED)
-			return 8*1024;
-		else
-			return 16*1024;
-	} else {
-		if (plane->i9xx_plane == PLANE_C)
-			return 4*1024;
-		else
-			return 8*1024;
-	}
-}
-
-static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	u32 dspcntr = 0;
-
-	if (crtc_state->gamma_enable)
-		dspcntr |= DISPPLANE_GAMMA_ENABLE;
-
-	if (crtc_state->csc_enable)
-		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
-
-	if (INTEL_GEN(dev_priv) < 5)
-		dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
-
-	return dspcntr;
-}
-
-static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
-			  const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv =
-		to_i915(plane_state->uapi.plane->dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	unsigned int rotation = plane_state->hw.rotation;
-	u32 dspcntr;
-
-	dspcntr = DISPLAY_PLANE_ENABLE;
-
-	if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
-	    IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
-		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
-
-	switch (fb->format->format) {
-	case DRM_FORMAT_C8:
-		dspcntr |= DISPPLANE_8BPP;
-		break;
-	case DRM_FORMAT_XRGB1555:
-		dspcntr |= DISPPLANE_BGRX555;
-		break;
-	case DRM_FORMAT_ARGB1555:
-		dspcntr |= DISPPLANE_BGRA555;
-		break;
-	case DRM_FORMAT_RGB565:
-		dspcntr |= DISPPLANE_BGRX565;
-		break;
-	case DRM_FORMAT_XRGB8888:
-		dspcntr |= DISPPLANE_BGRX888;
-		break;
-	case DRM_FORMAT_XBGR8888:
-		dspcntr |= DISPPLANE_RGBX888;
-		break;
-	case DRM_FORMAT_ARGB8888:
-		dspcntr |= DISPPLANE_BGRA888;
-		break;
-	case DRM_FORMAT_ABGR8888:
-		dspcntr |= DISPPLANE_RGBA888;
-		break;
-	case DRM_FORMAT_XRGB2101010:
-		dspcntr |= DISPPLANE_BGRX101010;
-		break;
-	case DRM_FORMAT_XBGR2101010:
-		dspcntr |= DISPPLANE_RGBX101010;
-		break;
-	case DRM_FORMAT_ARGB2101010:
-		dspcntr |= DISPPLANE_BGRA101010;
-		break;
-	case DRM_FORMAT_ABGR2101010:
-		dspcntr |= DISPPLANE_RGBA101010;
-		break;
-	case DRM_FORMAT_XBGR16161616F:
-		dspcntr |= DISPPLANE_RGBX161616;
-		break;
-	default:
-		MISSING_CASE(fb->format->format);
-		return 0;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 4 &&
-	    fb->modifier == I915_FORMAT_MOD_X_TILED)
-		dspcntr |= DISPPLANE_TILED;
-
-	if (rotation & DRM_MODE_ROTATE_180)
-		dspcntr |= DISPPLANE_ROTATE_180;
-
-	if (rotation & DRM_MODE_REFLECT_X)
-		dspcntr |= DISPPLANE_MIRROR;
-
-	return dspcntr;
-}
-
 int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 {
 	struct drm_i915_private *dev_priv =
@@ -4271,197 +4000,6 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 	return 0;
 }
 
-static bool i9xx_plane_has_windowing(struct intel_plane *plane)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-
-	if (IS_CHERRYVIEW(dev_priv))
-		return i9xx_plane == PLANE_B;
-	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-		return false;
-	else if (IS_GEN(dev_priv, 4))
-		return i9xx_plane == PLANE_C;
-	else
-		return i9xx_plane == PLANE_B ||
-			i9xx_plane == PLANE_C;
-}
-
-static int
-i9xx_plane_check(struct intel_crtc_state *crtc_state,
-		 struct intel_plane_state *plane_state)
-{
-	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-	int ret;
-
-	ret = chv_plane_check_rotation(plane_state);
-	if (ret)
-		return ret;
-
-	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
-						DRM_PLANE_HELPER_NO_SCALING,
-						DRM_PLANE_HELPER_NO_SCALING,
-						i9xx_plane_has_windowing(plane));
-	if (ret)
-		return ret;
-
-	ret = i9xx_check_plane_surface(plane_state);
-	if (ret)
-		return ret;
-
-	if (!plane_state->uapi.visible)
-		return 0;
-
-	ret = intel_plane_check_src_coordinates(plane_state);
-	if (ret)
-		return ret;
-
-	plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
-
-	return 0;
-}
-
-static void i9xx_update_plane(struct intel_plane *plane,
-			      const struct intel_crtc_state *crtc_state,
-			      const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-	u32 linear_offset;
-	int x = plane_state->color_plane[0].x;
-	int y = plane_state->color_plane[0].y;
-	int crtc_x = plane_state->uapi.dst.x1;
-	int crtc_y = plane_state->uapi.dst.y1;
-	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
-	int crtc_h = drm_rect_height(&plane_state->uapi.dst);
-	unsigned long irqflags;
-	u32 dspaddr_offset;
-	u32 dspcntr;
-
-	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
-
-	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
-
-	if (INTEL_GEN(dev_priv) >= 4)
-		dspaddr_offset = plane_state->color_plane[0].offset;
-	else
-		dspaddr_offset = linear_offset;
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
-			  plane_state->color_plane[0].stride);
-
-	if (INTEL_GEN(dev_priv) < 4) {
-		/*
-		 * PLANE_A doesn't actually have a full window
-		 * generator but let's assume we still need to
-		 * program whatever is there.
-		 */
-		intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
-				  (crtc_y << 16) | crtc_x);
-		intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
-				  ((crtc_h - 1) << 16) | (crtc_w - 1));
-	} else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
-		intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
-				  (crtc_y << 16) | crtc_x);
-		intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
-				  ((crtc_h - 1) << 16) | (crtc_w - 1));
-		intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
-	}
-
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
-		intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
-				  (y << 16) | x);
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
-				  linear_offset);
-		intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
-				  (y << 16) | x);
-	}
-
-	/*
-	 * The control register self-arms if the plane was previously
-	 * disabled. Try to make the plane enable atomic by writing
-	 * the control register just before the surface register.
-	 */
-	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
-	if (INTEL_GEN(dev_priv) >= 4)
-		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
-				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
-	else
-		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
-				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static void i9xx_disable_plane(struct intel_plane *plane,
-			       const struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-	unsigned long irqflags;
-	u32 dspcntr;
-
-	/*
-	 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
-	 * enable on ilk+ affect the pipe bottom color as
-	 * well, so we must configure them even if the plane
-	 * is disabled.
-	 *
-	 * On pre-g4x there is no way to gamma correct the
-	 * pipe bottom color but we'll keep on doing this
-	 * anyway so that the crtc state readout works correctly.
-	 */
-	dspcntr = i9xx_plane_ctl_crtc(crtc_state);
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
-	if (INTEL_GEN(dev_priv) >= 4)
-		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
-	else
-		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
-				    enum pipe *pipe)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum intel_display_power_domain power_domain;
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-	intel_wakeref_t wakeref;
-	bool ret;
-	u32 val;
-
-	/*
-	 * Not 100% correct for planes that can move between pipes,
-	 * but that's only the case for gen2-4 which don't have any
-	 * display power wells.
-	 */
-	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
-	if (!wakeref)
-		return false;
-
-	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
-
-	ret = val & DISPLAY_PLANE_ENABLE;
-
-	if (INTEL_GEN(dev_priv) >= 5)
-		*pipe = plane->pipe;
-	else
-		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
-			DISPPLANE_SEL_PIPE_SHIFT;
-
-	intel_display_power_put(dev_priv, power_domain, wakeref);
-
-	return ret;
-}
-
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
 {
 	struct drm_device *dev = intel_crtc->base.dev;
@@ -11908,33 +11446,6 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc,
 					 &pipe_config->fdi_m_n);
 }
 
-static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
-				   struct intel_crtc *crtc)
-{
-	memset(crtc_state, 0, sizeof(*crtc_state));
-
-	__drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
-
-	crtc_state->cpu_transcoder = INVALID_TRANSCODER;
-	crtc_state->master_transcoder = INVALID_TRANSCODER;
-	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
-	crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
-	crtc_state->scaler_state.scaler_id = -1;
-	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
-}
-
-static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
-{
-	struct intel_crtc_state *crtc_state;
-
-	crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
-
-	if (crtc_state)
-		intel_crtc_state_reset(crtc_state, crtc);
-
-	return crtc_state;
-}
-
 /* Returns the currently programmed mode of the given encoder. */
 struct drm_display_mode *
 intel_encoder_current_mode(struct intel_encoder *encoder)
@@ -11975,14 +11486,6 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
 	return mode;
 }
 
-static void intel_crtc_destroy(struct drm_crtc *crtc)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	drm_crtc_cleanup(crtc);
-	kfree(intel_crtc);
-}
-
 /**
  * intel_wm_need_update - Check whether watermarks need updating
  * @cur: current plane state
@@ -15186,17 +14689,6 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
 	return 0;
 }
 
-u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
-
-	if (!vblank->max_vblank_count)
-		return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
-
-	return crtc->base.funcs->get_vblank_counter(&crtc->base);
-}
-
 void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
 				  struct intel_crtc_state *crtc_state)
 {
@@ -16249,336 +15741,6 @@ void intel_plane_destroy(struct drm_plane *plane)
 	kfree(to_intel_plane(plane));
 }
 
-static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
-					    u32 format, u64 modifier)
-{
-	switch (modifier) {
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-		break;
-	default:
-		return false;
-	}
-
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_XRGB1555:
-	case DRM_FORMAT_XRGB8888:
-		return modifier == DRM_FORMAT_MOD_LINEAR ||
-			modifier == I915_FORMAT_MOD_X_TILED;
-	default:
-		return false;
-	}
-}
-
-static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
-					    u32 format, u64 modifier)
-{
-	switch (modifier) {
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-		break;
-	default:
-		return false;
-	}
-
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_XBGR16161616F:
-		return modifier == DRM_FORMAT_MOD_LINEAR ||
-			modifier == I915_FORMAT_MOD_X_TILED;
-	default:
-		return false;
-	}
-}
-
-static const struct drm_plane_funcs i965_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = intel_plane_destroy,
-	.atomic_duplicate_state = intel_plane_duplicate_state,
-	.atomic_destroy_state = intel_plane_destroy_state,
-	.format_mod_supported = i965_plane_format_mod_supported,
-};
-
-static const struct drm_plane_funcs i8xx_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = intel_plane_destroy,
-	.atomic_duplicate_state = intel_plane_duplicate_state,
-	.atomic_destroy_state = intel_plane_destroy_state,
-	.format_mod_supported = i8xx_plane_format_mod_supported,
-};
-
-static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
-			       enum i9xx_plane_id i9xx_plane)
-{
-	if (!HAS_FBC(dev_priv))
-		return false;
-
-	if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
-		return i9xx_plane == PLANE_A; /* tied to pipe A */
-	else if (IS_IVYBRIDGE(dev_priv))
-		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
-			i9xx_plane == PLANE_C;
-	else if (INTEL_GEN(dev_priv) >= 4)
-		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
-	else
-		return i9xx_plane == PLANE_A;
-}
-
-static struct intel_plane *
-intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
-	struct intel_plane *plane;
-	const struct drm_plane_funcs *plane_funcs;
-	unsigned int supported_rotations;
-	const u32 *formats;
-	int num_formats;
-	int ret, zpos;
-
-	if (INTEL_GEN(dev_priv) >= 9)
-		return skl_universal_plane_create(dev_priv, pipe,
-						  PLANE_PRIMARY);
-
-	plane = intel_plane_alloc();
-	if (IS_ERR(plane))
-		return plane;
-
-	plane->pipe = pipe;
-	/*
-	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
-	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
-	 */
-	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
-	    INTEL_NUM_PIPES(dev_priv) == 2)
-		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
-	else
-		plane->i9xx_plane = (enum i9xx_plane_id) pipe;
-	plane->id = PLANE_PRIMARY;
-	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
-
-	plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
-	if (plane->has_fbc) {
-		struct intel_fbc *fbc = &dev_priv->fbc;
-
-		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
-	}
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		formats = vlv_primary_formats;
-		num_formats = ARRAY_SIZE(vlv_primary_formats);
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		/*
-		 * WaFP16GammaEnabling:ivb
-		 * "Workaround : When using the 64-bit format, the plane
-		 *  output on each color channel has one quarter amplitude.
-		 *  It can be brought up to full amplitude by using pipe
-		 *  gamma correction or pipe color space conversion to
-		 *  multiply the plane output by four."
-		 *
-		 * There is no dedicated plane gamma for the primary plane,
-		 * and using the pipe gamma/csc could conflict with other
-		 * planes, so we choose not to expose fp16 on IVB primary
-		 * planes. HSW primary planes no longer have this problem.
-		 */
-		if (IS_IVYBRIDGE(dev_priv)) {
-			formats = ivb_primary_formats;
-			num_formats = ARRAY_SIZE(ivb_primary_formats);
-		} else {
-			formats = i965_primary_formats;
-			num_formats = ARRAY_SIZE(i965_primary_formats);
-		}
-	} else {
-		formats = i8xx_primary_formats;
-		num_formats = ARRAY_SIZE(i8xx_primary_formats);
-	}
-
-	if (INTEL_GEN(dev_priv) >= 4)
-		plane_funcs = &i965_plane_funcs;
-	else
-		plane_funcs = &i8xx_plane_funcs;
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		plane->min_cdclk = vlv_plane_min_cdclk;
-	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
-		plane->min_cdclk = hsw_plane_min_cdclk;
-	else if (IS_IVYBRIDGE(dev_priv))
-		plane->min_cdclk = ivb_plane_min_cdclk;
-	else
-		plane->min_cdclk = i9xx_plane_min_cdclk;
-
-	plane->max_stride = i9xx_plane_max_stride;
-	plane->update_plane = i9xx_update_plane;
-	plane->disable_plane = i9xx_disable_plane;
-	plane->get_hw_state = i9xx_plane_get_hw_state;
-	plane->check_plane = i9xx_plane_check;
-
-	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
-					       0, plane_funcs,
-					       formats, num_formats,
-					       i9xx_format_modifiers,
-					       DRM_PLANE_TYPE_PRIMARY,
-					       "primary %c", pipe_name(pipe));
-	else
-		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
-					       0, plane_funcs,
-					       formats, num_formats,
-					       i9xx_format_modifiers,
-					       DRM_PLANE_TYPE_PRIMARY,
-					       "plane %c",
-					       plane_name(plane->i9xx_plane));
-	if (ret)
-		goto fail;
-
-	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
-		supported_rotations =
-			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
-			DRM_MODE_REFLECT_X;
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		supported_rotations =
-			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
-	} else {
-		supported_rotations = DRM_MODE_ROTATE_0;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 4)
-		drm_plane_create_rotation_property(&plane->base,
-						   DRM_MODE_ROTATE_0,
-						   supported_rotations);
-
-	zpos = 0;
-	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
-
-	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
-
-	return plane;
-
-fail:
-	intel_plane_free(plane);
-
-	return ERR_PTR(ret);
-}
-
-static int intel_crtc_late_register(struct drm_crtc *crtc)
-{
-	intel_crtc_debugfs_add(crtc);
-	return 0;
-}
-
-#define INTEL_CRTC_FUNCS \
-	.gamma_set = drm_atomic_helper_legacy_gamma_set, \
-	.set_config = drm_atomic_helper_set_config, \
-	.destroy = intel_crtc_destroy, \
-	.page_flip = drm_atomic_helper_page_flip, \
-	.atomic_duplicate_state = intel_crtc_duplicate_state, \
-	.atomic_destroy_state = intel_crtc_destroy_state, \
-	.set_crc_source = intel_crtc_set_crc_source, \
-	.verify_crc_source = intel_crtc_verify_crc_source, \
-	.get_crc_sources = intel_crtc_get_crc_sources, \
-	.late_register = intel_crtc_late_register
-
-static const struct drm_crtc_funcs bdw_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = g4x_get_vblank_counter,
-	.enable_vblank = bdw_enable_vblank,
-	.disable_vblank = bdw_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs ilk_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = g4x_get_vblank_counter,
-	.enable_vblank = ilk_enable_vblank,
-	.disable_vblank = ilk_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs g4x_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = g4x_get_vblank_counter,
-	.enable_vblank = i965_enable_vblank,
-	.disable_vblank = i965_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i965_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = i915_get_vblank_counter,
-	.enable_vblank = i965_enable_vblank,
-	.disable_vblank = i965_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i915gm_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = i915_get_vblank_counter,
-	.enable_vblank = i915gm_enable_vblank,
-	.disable_vblank = i915gm_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i915_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = i915_get_vblank_counter,
-	.enable_vblank = i8xx_enable_vblank,
-	.disable_vblank = i8xx_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i8xx_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	/* no hw vblank counter */
-	.enable_vblank = i8xx_enable_vblank,
-	.disable_vblank = i8xx_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static struct intel_crtc *intel_crtc_alloc(void)
-{
-	struct intel_crtc_state *crtc_state;
-	struct intel_crtc *crtc;
-
-	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
-	if (!crtc)
-		return ERR_PTR(-ENOMEM);
-
-	crtc_state = intel_crtc_state_alloc(crtc);
-	if (!crtc_state) {
-		kfree(crtc);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	crtc->base.state = &crtc_state->uapi;
-	crtc->config = crtc_state;
-
-	return crtc;
-}
-
-static void intel_crtc_free(struct intel_crtc *crtc)
-{
-	intel_crtc_destroy_state(&crtc->base, crtc->base.state);
-	kfree(crtc);
-}
-
 static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
 {
 	struct intel_plane *plane;
@@ -16591,100 +15753,6 @@ static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
 	}
 }
 
-static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
-	struct intel_plane *primary, *cursor;
-	const struct drm_crtc_funcs *funcs;
-	struct intel_crtc *crtc;
-	int sprite, ret;
-
-	crtc = intel_crtc_alloc();
-	if (IS_ERR(crtc))
-		return PTR_ERR(crtc);
-
-	crtc->pipe = pipe;
-	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
-
-	primary = intel_primary_plane_create(dev_priv, pipe);
-	if (IS_ERR(primary)) {
-		ret = PTR_ERR(primary);
-		goto fail;
-	}
-	crtc->plane_ids_mask |= BIT(primary->id);
-
-	for_each_sprite(dev_priv, pipe, sprite) {
-		struct intel_plane *plane;
-
-		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
-		if (IS_ERR(plane)) {
-			ret = PTR_ERR(plane);
-			goto fail;
-		}
-		crtc->plane_ids_mask |= BIT(plane->id);
-	}
-
-	cursor = intel_cursor_plane_create(dev_priv, pipe);
-	if (IS_ERR(cursor)) {
-		ret = PTR_ERR(cursor);
-		goto fail;
-	}
-	crtc->plane_ids_mask |= BIT(cursor->id);
-
-	if (HAS_GMCH(dev_priv)) {
-		if (IS_CHERRYVIEW(dev_priv) ||
-		    IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
-			funcs = &g4x_crtc_funcs;
-		else if (IS_GEN(dev_priv, 4))
-			funcs = &i965_crtc_funcs;
-		else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
-			funcs = &i915gm_crtc_funcs;
-		else if (IS_GEN(dev_priv, 3))
-			funcs = &i915_crtc_funcs;
-		else
-			funcs = &i8xx_crtc_funcs;
-	} else {
-		if (INTEL_GEN(dev_priv) >= 8)
-			funcs = &bdw_crtc_funcs;
-		else
-			funcs = &ilk_crtc_funcs;
-	}
-
-	ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
-					&primary->base, &cursor->base,
-					funcs, "pipe %c", pipe_name(pipe));
-	if (ret)
-		goto fail;
-
-	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
-	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
-	dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
-
-	if (INTEL_GEN(dev_priv) < 9) {
-		enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
-
-		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
-		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
-		dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 10)
-		drm_crtc_create_scaling_filter_property(&crtc->base,
-						BIT(DRM_SCALING_FILTER_DEFAULT) |
-						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
-
-	intel_color_init(crtc);
-
-	intel_crtc_crc_init(crtc);
-
-	drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
-
-	return 0;
-
-fail:
-	intel_crtc_free(crtc);
-
-	return ret;
-}
 
 int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
 				      struct drm_file *file)
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index f0a5bf69656f..0eba91d18e96 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -659,6 +659,13 @@ struct intel_plane *
 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
 			  enum pipe pipe);
 
+/* crtc */
+u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
+int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
+struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
+void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
+			    struct intel_crtc *crtc);
+
 /* modesetting */
 void intel_modeset_init_hw(struct drm_i915_private *i915);
 int intel_modeset_init_noirq(struct drm_i915_private *i915);
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 6/9] drm/i915: refactor pll code out into intel_dpll_legacy.c
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (4 preceding siblings ...)
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 5/9] drm/i915: refactor some crtc code out of intel display Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10 15:18   ` Ville Syrjälä
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 7/9] drm/i915: split fdi code out from intel_display.c Dave Airlie
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

This pulls a large chunk of the pll calculation code out of
intel_display.c to a new file.

One function makse sense to be an inline, otherwise this
is pretty much a straight copy cover. also all the
remaining hooks for g45 and older end up the same now.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/Makefile                 |    1 +
 drivers/gpu/drm/i915/display/intel_display.c  | 1393 +----------------
 drivers/gpu/drm/i915/display/intel_display.h  |   13 +-
 .../drm/i915/display/intel_display_types.h    |    5 +
 .../gpu/drm/i915/display/intel_dpll_legacy.c  | 1370 ++++++++++++++++
 5 files changed, 1398 insertions(+), 1384 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dpll_legacy.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index ffec257702af..accefd7b380e 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -202,6 +202,7 @@ i915-y += \
 	display/intel_display.o \
 	display/intel_display_power.o \
 	display/intel_dpio_phy.o \
+	display/intel_dpll_legacy.o \
 	display/intel_dpll_mgr.o \
 	display/intel_dsb.o \
 	display/intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 2507a72ee249..ff5b51dea661 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -113,17 +113,6 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
 static void intel_modeset_setup_hw_state(struct drm_device *dev,
 					 struct drm_modeset_acquire_ctx *ctx);
 
-struct intel_limit {
-	struct {
-		int min, max;
-	} dot, vco, n, m, m1, m2, p, p1;
-
-	struct {
-		int dot_limit;
-		int p2_slow, p2_fast;
-	} p2;
-};
-
 /* returns HPLL frequency in kHz */
 int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
 {
@@ -191,271 +180,6 @@ static u32 intel_fdi_link_freq(struct drm_i915_private *dev_priv,
 		return dev_priv->fdi_pll_freq;
 }
 
-static const struct intel_limit intel_limits_i8xx_dac = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 908000, .max = 1512000 },
-	.n = { .min = 2, .max = 16 },
-	.m = { .min = 96, .max = 140 },
-	.m1 = { .min = 18, .max = 26 },
-	.m2 = { .min = 6, .max = 16 },
-	.p = { .min = 4, .max = 128 },
-	.p1 = { .min = 2, .max = 33 },
-	.p2 = { .dot_limit = 165000,
-		.p2_slow = 4, .p2_fast = 2 },
-};
-
-static const struct intel_limit intel_limits_i8xx_dvo = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 908000, .max = 1512000 },
-	.n = { .min = 2, .max = 16 },
-	.m = { .min = 96, .max = 140 },
-	.m1 = { .min = 18, .max = 26 },
-	.m2 = { .min = 6, .max = 16 },
-	.p = { .min = 4, .max = 128 },
-	.p1 = { .min = 2, .max = 33 },
-	.p2 = { .dot_limit = 165000,
-		.p2_slow = 4, .p2_fast = 4 },
-};
-
-static const struct intel_limit intel_limits_i8xx_lvds = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 908000, .max = 1512000 },
-	.n = { .min = 2, .max = 16 },
-	.m = { .min = 96, .max = 140 },
-	.m1 = { .min = 18, .max = 26 },
-	.m2 = { .min = 6, .max = 16 },
-	.p = { .min = 4, .max = 128 },
-	.p1 = { .min = 1, .max = 6 },
-	.p2 = { .dot_limit = 165000,
-		.p2_slow = 14, .p2_fast = 7 },
-};
-
-static const struct intel_limit intel_limits_i9xx_sdvo = {
-	.dot = { .min = 20000, .max = 400000 },
-	.vco = { .min = 1400000, .max = 2800000 },
-	.n = { .min = 1, .max = 6 },
-	.m = { .min = 70, .max = 120 },
-	.m1 = { .min = 8, .max = 18 },
-	.m2 = { .min = 3, .max = 7 },
-	.p = { .min = 5, .max = 80 },
-	.p1 = { .min = 1, .max = 8 },
-	.p2 = { .dot_limit = 200000,
-		.p2_slow = 10, .p2_fast = 5 },
-};
-
-static const struct intel_limit intel_limits_i9xx_lvds = {
-	.dot = { .min = 20000, .max = 400000 },
-	.vco = { .min = 1400000, .max = 2800000 },
-	.n = { .min = 1, .max = 6 },
-	.m = { .min = 70, .max = 120 },
-	.m1 = { .min = 8, .max = 18 },
-	.m2 = { .min = 3, .max = 7 },
-	.p = { .min = 7, .max = 98 },
-	.p1 = { .min = 1, .max = 8 },
-	.p2 = { .dot_limit = 112000,
-		.p2_slow = 14, .p2_fast = 7 },
-};
-
-
-static const struct intel_limit intel_limits_g4x_sdvo = {
-	.dot = { .min = 25000, .max = 270000 },
-	.vco = { .min = 1750000, .max = 3500000},
-	.n = { .min = 1, .max = 4 },
-	.m = { .min = 104, .max = 138 },
-	.m1 = { .min = 17, .max = 23 },
-	.m2 = { .min = 5, .max = 11 },
-	.p = { .min = 10, .max = 30 },
-	.p1 = { .min = 1, .max = 3},
-	.p2 = { .dot_limit = 270000,
-		.p2_slow = 10,
-		.p2_fast = 10
-	},
-};
-
-static const struct intel_limit intel_limits_g4x_hdmi = {
-	.dot = { .min = 22000, .max = 400000 },
-	.vco = { .min = 1750000, .max = 3500000},
-	.n = { .min = 1, .max = 4 },
-	.m = { .min = 104, .max = 138 },
-	.m1 = { .min = 16, .max = 23 },
-	.m2 = { .min = 5, .max = 11 },
-	.p = { .min = 5, .max = 80 },
-	.p1 = { .min = 1, .max = 8},
-	.p2 = { .dot_limit = 165000,
-		.p2_slow = 10, .p2_fast = 5 },
-};
-
-static const struct intel_limit intel_limits_g4x_single_channel_lvds = {
-	.dot = { .min = 20000, .max = 115000 },
-	.vco = { .min = 1750000, .max = 3500000 },
-	.n = { .min = 1, .max = 3 },
-	.m = { .min = 104, .max = 138 },
-	.m1 = { .min = 17, .max = 23 },
-	.m2 = { .min = 5, .max = 11 },
-	.p = { .min = 28, .max = 112 },
-	.p1 = { .min = 2, .max = 8 },
-	.p2 = { .dot_limit = 0,
-		.p2_slow = 14, .p2_fast = 14
-	},
-};
-
-static const struct intel_limit intel_limits_g4x_dual_channel_lvds = {
-	.dot = { .min = 80000, .max = 224000 },
-	.vco = { .min = 1750000, .max = 3500000 },
-	.n = { .min = 1, .max = 3 },
-	.m = { .min = 104, .max = 138 },
-	.m1 = { .min = 17, .max = 23 },
-	.m2 = { .min = 5, .max = 11 },
-	.p = { .min = 14, .max = 42 },
-	.p1 = { .min = 2, .max = 6 },
-	.p2 = { .dot_limit = 0,
-		.p2_slow = 7, .p2_fast = 7
-	},
-};
-
-static const struct intel_limit pnv_limits_sdvo = {
-	.dot = { .min = 20000, .max = 400000},
-	.vco = { .min = 1700000, .max = 3500000 },
-	/* Pineview's Ncounter is a ring counter */
-	.n = { .min = 3, .max = 6 },
-	.m = { .min = 2, .max = 256 },
-	/* Pineview only has one combined m divider, which we treat as m2. */
-	.m1 = { .min = 0, .max = 0 },
-	.m2 = { .min = 0, .max = 254 },
-	.p = { .min = 5, .max = 80 },
-	.p1 = { .min = 1, .max = 8 },
-	.p2 = { .dot_limit = 200000,
-		.p2_slow = 10, .p2_fast = 5 },
-};
-
-static const struct intel_limit pnv_limits_lvds = {
-	.dot = { .min = 20000, .max = 400000 },
-	.vco = { .min = 1700000, .max = 3500000 },
-	.n = { .min = 3, .max = 6 },
-	.m = { .min = 2, .max = 256 },
-	.m1 = { .min = 0, .max = 0 },
-	.m2 = { .min = 0, .max = 254 },
-	.p = { .min = 7, .max = 112 },
-	.p1 = { .min = 1, .max = 8 },
-	.p2 = { .dot_limit = 112000,
-		.p2_slow = 14, .p2_fast = 14 },
-};
-
-/* Ironlake / Sandybridge
- *
- * We calculate clock using (register_value + 2) for N/M1/M2, so here
- * the range value for them is (actual_value - 2).
- */
-static const struct intel_limit ilk_limits_dac = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 1760000, .max = 3510000 },
-	.n = { .min = 1, .max = 5 },
-	.m = { .min = 79, .max = 127 },
-	.m1 = { .min = 12, .max = 22 },
-	.m2 = { .min = 5, .max = 9 },
-	.p = { .min = 5, .max = 80 },
-	.p1 = { .min = 1, .max = 8 },
-	.p2 = { .dot_limit = 225000,
-		.p2_slow = 10, .p2_fast = 5 },
-};
-
-static const struct intel_limit ilk_limits_single_lvds = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 1760000, .max = 3510000 },
-	.n = { .min = 1, .max = 3 },
-	.m = { .min = 79, .max = 118 },
-	.m1 = { .min = 12, .max = 22 },
-	.m2 = { .min = 5, .max = 9 },
-	.p = { .min = 28, .max = 112 },
-	.p1 = { .min = 2, .max = 8 },
-	.p2 = { .dot_limit = 225000,
-		.p2_slow = 14, .p2_fast = 14 },
-};
-
-static const struct intel_limit ilk_limits_dual_lvds = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 1760000, .max = 3510000 },
-	.n = { .min = 1, .max = 3 },
-	.m = { .min = 79, .max = 127 },
-	.m1 = { .min = 12, .max = 22 },
-	.m2 = { .min = 5, .max = 9 },
-	.p = { .min = 14, .max = 56 },
-	.p1 = { .min = 2, .max = 8 },
-	.p2 = { .dot_limit = 225000,
-		.p2_slow = 7, .p2_fast = 7 },
-};
-
-/* LVDS 100mhz refclk limits. */
-static const struct intel_limit ilk_limits_single_lvds_100m = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 1760000, .max = 3510000 },
-	.n = { .min = 1, .max = 2 },
-	.m = { .min = 79, .max = 126 },
-	.m1 = { .min = 12, .max = 22 },
-	.m2 = { .min = 5, .max = 9 },
-	.p = { .min = 28, .max = 112 },
-	.p1 = { .min = 2, .max = 8 },
-	.p2 = { .dot_limit = 225000,
-		.p2_slow = 14, .p2_fast = 14 },
-};
-
-static const struct intel_limit ilk_limits_dual_lvds_100m = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 1760000, .max = 3510000 },
-	.n = { .min = 1, .max = 3 },
-	.m = { .min = 79, .max = 126 },
-	.m1 = { .min = 12, .max = 22 },
-	.m2 = { .min = 5, .max = 9 },
-	.p = { .min = 14, .max = 42 },
-	.p1 = { .min = 2, .max = 6 },
-	.p2 = { .dot_limit = 225000,
-		.p2_slow = 7, .p2_fast = 7 },
-};
-
-static const struct intel_limit intel_limits_vlv = {
-	 /*
-	  * These are the data rate limits (measured in fast clocks)
-	  * since those are the strictest limits we have. The fast
-	  * clock and actual rate limits are more relaxed, so checking
-	  * them would make no difference.
-	  */
-	.dot = { .min = 25000 * 5, .max = 270000 * 5 },
-	.vco = { .min = 4000000, .max = 6000000 },
-	.n = { .min = 1, .max = 7 },
-	.m1 = { .min = 2, .max = 3 },
-	.m2 = { .min = 11, .max = 156 },
-	.p1 = { .min = 2, .max = 3 },
-	.p2 = { .p2_slow = 2, .p2_fast = 20 }, /* slow=min, fast=max */
-};
-
-static const struct intel_limit intel_limits_chv = {
-	/*
-	 * These are the data rate limits (measured in fast clocks)
-	 * since those are the strictest limits we have.  The fast
-	 * clock and actual rate limits are more relaxed, so checking
-	 * them would make no difference.
-	 */
-	.dot = { .min = 25000 * 5, .max = 540000 * 5},
-	.vco = { .min = 4800000, .max = 6480000 },
-	.n = { .min = 1, .max = 1 },
-	.m1 = { .min = 2, .max = 2 },
-	.m2 = { .min = 24 << 22, .max = 175 << 22 },
-	.p1 = { .min = 2, .max = 4 },
-	.p2 = {	.p2_slow = 1, .p2_fast = 14 },
-};
-
-static const struct intel_limit intel_limits_bxt = {
-	/* FIXME: find real dot limits */
-	.dot = { .min = 0, .max = INT_MAX },
-	.vco = { .min = 4800000, .max = 6700000 },
-	.n = { .min = 1, .max = 1 },
-	.m1 = { .min = 2, .max = 2 },
-	/* FIXME: find real m2 limits */
-	.m2 = { .min = 2 << 22, .max = 255 << 22 },
-	.p1 = { .min = 2, .max = 4 },
-	.p2 = { .p2_slow = 1, .p2_fast = 20 },
-};
-
 /* WA Display #0827: Gen9:all */
 static void
 skl_wa_827(struct drm_i915_private *dev_priv, enum pipe pipe, bool enable)
@@ -500,483 +224,6 @@ is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state)
 		is_trans_port_sync_slave(crtc_state);
 }
 
-/*
- * Platform specific helpers to calculate the port PLL loopback- (clock.m),
- * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
- * (clock.dot) clock rates. This fast dot clock is fed to the port's IO logic.
- * The helpers' return value is the rate of the clock that is fed to the
- * display engine's pipe which can be the above fast dot clock rate or a
- * divided-down version of it.
- */
-/* m1 is reserved as 0 in Pineview, n is a ring counter */
-static int pnv_calc_dpll_params(int refclk, struct dpll *clock)
-{
-	clock->m = clock->m2 + 2;
-	clock->p = clock->p1 * clock->p2;
-	if (WARN_ON(clock->n == 0 || clock->p == 0))
-		return 0;
-	clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
-	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
-
-	return clock->dot;
-}
-
-static u32 i9xx_dpll_compute_m(struct dpll *dpll)
-{
-	return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
-}
-
-static int i9xx_calc_dpll_params(int refclk, struct dpll *clock)
-{
-	clock->m = i9xx_dpll_compute_m(clock);
-	clock->p = clock->p1 * clock->p2;
-	if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
-		return 0;
-	clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
-	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
-
-	return clock->dot;
-}
-
-static int vlv_calc_dpll_params(int refclk, struct dpll *clock)
-{
-	clock->m = clock->m1 * clock->m2;
-	clock->p = clock->p1 * clock->p2;
-	if (WARN_ON(clock->n == 0 || clock->p == 0))
-		return 0;
-	clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
-	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
-
-	return clock->dot / 5;
-}
-
-int chv_calc_dpll_params(int refclk, struct dpll *clock)
-{
-	clock->m = clock->m1 * clock->m2;
-	clock->p = clock->p1 * clock->p2;
-	if (WARN_ON(clock->n == 0 || clock->p == 0))
-		return 0;
-	clock->vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m),
-					   clock->n << 22);
-	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
-
-	return clock->dot / 5;
-}
-
-/*
- * Returns whether the given set of divisors are valid for a given refclk with
- * the given connectors.
- */
-static bool intel_pll_is_valid(struct drm_i915_private *dev_priv,
-			       const struct intel_limit *limit,
-			       const struct dpll *clock)
-{
-	if (clock->n < limit->n.min || limit->n.max < clock->n)
-		return false;
-	if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
-		return false;
-	if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
-		return false;
-	if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
-		return false;
-
-	if (!IS_PINEVIEW(dev_priv) && !IS_VALLEYVIEW(dev_priv) &&
-	    !IS_CHERRYVIEW(dev_priv) && !IS_GEN9_LP(dev_priv))
-		if (clock->m1 <= clock->m2)
-			return false;
-
-	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
-	    !IS_GEN9_LP(dev_priv)) {
-		if (clock->p < limit->p.min || limit->p.max < clock->p)
-			return false;
-		if (clock->m < limit->m.min || limit->m.max < clock->m)
-			return false;
-	}
-
-	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
-		return false;
-	/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
-	 * connector, etc., rather than just a single range.
-	 */
-	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
-		return false;
-
-	return true;
-}
-
-static int
-i9xx_select_p2_div(const struct intel_limit *limit,
-		   const struct intel_crtc_state *crtc_state,
-		   int target)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		/*
-		 * For LVDS just rely on its current settings for dual-channel.
-		 * We haven't figured out how to reliably set up different
-		 * single/dual channel state, if we even can.
-		 */
-		if (intel_is_dual_link_lvds(dev_priv))
-			return limit->p2.p2_fast;
-		else
-			return limit->p2.p2_slow;
-	} else {
-		if (target < limit->p2.dot_limit)
-			return limit->p2.p2_slow;
-		else
-			return limit->p2.p2_fast;
-	}
-}
-
-/*
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- *
- * Target and reference clocks are specified in kHz.
- *
- * If match_clock is provided, then best_clock P divider must match the P
- * divider from @match_clock used for LVDS downclocking.
- */
-static bool
-i9xx_find_best_dpll(const struct intel_limit *limit,
-		    struct intel_crtc_state *crtc_state,
-		    int target, int refclk, struct dpll *match_clock,
-		    struct dpll *best_clock)
-{
-	struct drm_device *dev = crtc_state->uapi.crtc->dev;
-	struct dpll clock;
-	int err = target;
-
-	memset(best_clock, 0, sizeof(*best_clock));
-
-	clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
-
-	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
-	     clock.m1++) {
-		for (clock.m2 = limit->m2.min;
-		     clock.m2 <= limit->m2.max; clock.m2++) {
-			if (clock.m2 >= clock.m1)
-				break;
-			for (clock.n = limit->n.min;
-			     clock.n <= limit->n.max; clock.n++) {
-				for (clock.p1 = limit->p1.min;
-					clock.p1 <= limit->p1.max; clock.p1++) {
-					int this_err;
-
-					i9xx_calc_dpll_params(refclk, &clock);
-					if (!intel_pll_is_valid(to_i915(dev),
-								limit,
-								&clock))
-						continue;
-					if (match_clock &&
-					    clock.p != match_clock->p)
-						continue;
-
-					this_err = abs(clock.dot - target);
-					if (this_err < err) {
-						*best_clock = clock;
-						err = this_err;
-					}
-				}
-			}
-		}
-	}
-
-	return (err != target);
-}
-
-/*
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- *
- * Target and reference clocks are specified in kHz.
- *
- * If match_clock is provided, then best_clock P divider must match the P
- * divider from @match_clock used for LVDS downclocking.
- */
-static bool
-pnv_find_best_dpll(const struct intel_limit *limit,
-		   struct intel_crtc_state *crtc_state,
-		   int target, int refclk, struct dpll *match_clock,
-		   struct dpll *best_clock)
-{
-	struct drm_device *dev = crtc_state->uapi.crtc->dev;
-	struct dpll clock;
-	int err = target;
-
-	memset(best_clock, 0, sizeof(*best_clock));
-
-	clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
-
-	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
-	     clock.m1++) {
-		for (clock.m2 = limit->m2.min;
-		     clock.m2 <= limit->m2.max; clock.m2++) {
-			for (clock.n = limit->n.min;
-			     clock.n <= limit->n.max; clock.n++) {
-				for (clock.p1 = limit->p1.min;
-					clock.p1 <= limit->p1.max; clock.p1++) {
-					int this_err;
-
-					pnv_calc_dpll_params(refclk, &clock);
-					if (!intel_pll_is_valid(to_i915(dev),
-								limit,
-								&clock))
-						continue;
-					if (match_clock &&
-					    clock.p != match_clock->p)
-						continue;
-
-					this_err = abs(clock.dot - target);
-					if (this_err < err) {
-						*best_clock = clock;
-						err = this_err;
-					}
-				}
-			}
-		}
-	}
-
-	return (err != target);
-}
-
-/*
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- *
- * Target and reference clocks are specified in kHz.
- *
- * If match_clock is provided, then best_clock P divider must match the P
- * divider from @match_clock used for LVDS downclocking.
- */
-static bool
-g4x_find_best_dpll(const struct intel_limit *limit,
-		   struct intel_crtc_state *crtc_state,
-		   int target, int refclk, struct dpll *match_clock,
-		   struct dpll *best_clock)
-{
-	struct drm_device *dev = crtc_state->uapi.crtc->dev;
-	struct dpll clock;
-	int max_n;
-	bool found = false;
-	/* approximately equals target * 0.00585 */
-	int err_most = (target >> 8) + (target >> 9);
-
-	memset(best_clock, 0, sizeof(*best_clock));
-
-	clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
-
-	max_n = limit->n.max;
-	/* based on hardware requirement, prefer smaller n to precision */
-	for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
-		/* based on hardware requirement, prefere larger m1,m2 */
-		for (clock.m1 = limit->m1.max;
-		     clock.m1 >= limit->m1.min; clock.m1--) {
-			for (clock.m2 = limit->m2.max;
-			     clock.m2 >= limit->m2.min; clock.m2--) {
-				for (clock.p1 = limit->p1.max;
-				     clock.p1 >= limit->p1.min; clock.p1--) {
-					int this_err;
-
-					i9xx_calc_dpll_params(refclk, &clock);
-					if (!intel_pll_is_valid(to_i915(dev),
-								limit,
-								&clock))
-						continue;
-
-					this_err = abs(clock.dot - target);
-					if (this_err < err_most) {
-						*best_clock = clock;
-						err_most = this_err;
-						max_n = clock.n;
-						found = true;
-					}
-				}
-			}
-		}
-	}
-	return found;
-}
-
-/*
- * Check if the calculated PLL configuration is more optimal compared to the
- * best configuration and error found so far. Return the calculated error.
- */
-static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
-			       const struct dpll *calculated_clock,
-			       const struct dpll *best_clock,
-			       unsigned int best_error_ppm,
-			       unsigned int *error_ppm)
-{
-	/*
-	 * For CHV ignore the error and consider only the P value.
-	 * Prefer a bigger P value based on HW requirements.
-	 */
-	if (IS_CHERRYVIEW(to_i915(dev))) {
-		*error_ppm = 0;
-
-		return calculated_clock->p > best_clock->p;
-	}
-
-	if (drm_WARN_ON_ONCE(dev, !target_freq))
-		return false;
-
-	*error_ppm = div_u64(1000000ULL *
-				abs(target_freq - calculated_clock->dot),
-			     target_freq);
-	/*
-	 * Prefer a better P value over a better (smaller) error if the error
-	 * is small. Ensure this preference for future configurations too by
-	 * setting the error to 0.
-	 */
-	if (*error_ppm < 100 && calculated_clock->p > best_clock->p) {
-		*error_ppm = 0;
-
-		return true;
-	}
-
-	return *error_ppm + 10 < best_error_ppm;
-}
-
-/*
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- */
-static bool
-vlv_find_best_dpll(const struct intel_limit *limit,
-		   struct intel_crtc_state *crtc_state,
-		   int target, int refclk, struct dpll *match_clock,
-		   struct dpll *best_clock)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_device *dev = crtc->base.dev;
-	struct dpll clock;
-	unsigned int bestppm = 1000000;
-	/* min update 19.2 MHz */
-	int max_n = min(limit->n.max, refclk / 19200);
-	bool found = false;
-
-	target *= 5; /* fast clock */
-
-	memset(best_clock, 0, sizeof(*best_clock));
-
-	/* based on hardware requirement, prefer smaller n to precision */
-	for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
-		for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
-			for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow;
-			     clock.p2 -= clock.p2 > 10 ? 2 : 1) {
-				clock.p = clock.p1 * clock.p2;
-				/* based on hardware requirement, prefer bigger m1,m2 values */
-				for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
-					unsigned int ppm;
-
-					clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n,
-								     refclk * clock.m1);
-
-					vlv_calc_dpll_params(refclk, &clock);
-
-					if (!intel_pll_is_valid(to_i915(dev),
-								limit,
-								&clock))
-						continue;
-
-					if (!vlv_PLL_is_optimal(dev, target,
-								&clock,
-								best_clock,
-								bestppm, &ppm))
-						continue;
-
-					*best_clock = clock;
-					bestppm = ppm;
-					found = true;
-				}
-			}
-		}
-	}
-
-	return found;
-}
-
-/*
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- */
-static bool
-chv_find_best_dpll(const struct intel_limit *limit,
-		   struct intel_crtc_state *crtc_state,
-		   int target, int refclk, struct dpll *match_clock,
-		   struct dpll *best_clock)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_device *dev = crtc->base.dev;
-	unsigned int best_error_ppm;
-	struct dpll clock;
-	u64 m2;
-	int found = false;
-
-	memset(best_clock, 0, sizeof(*best_clock));
-	best_error_ppm = 1000000;
-
-	/*
-	 * Based on hardware doc, the n always set to 1, and m1 always
-	 * set to 2.  If requires to support 200Mhz refclk, we need to
-	 * revisit this because n may not 1 anymore.
-	 */
-	clock.n = 1;
-	clock.m1 = 2;
-	target *= 5;	/* fast clock */
-
-	for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
-		for (clock.p2 = limit->p2.p2_fast;
-				clock.p2 >= limit->p2.p2_slow;
-				clock.p2 -= clock.p2 > 10 ? 2 : 1) {
-			unsigned int error_ppm;
-
-			clock.p = clock.p1 * clock.p2;
-
-			m2 = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(target, clock.p * clock.n) << 22,
-						   refclk * clock.m1);
-
-			if (m2 > INT_MAX/clock.m1)
-				continue;
-
-			clock.m2 = m2;
-
-			chv_calc_dpll_params(refclk, &clock);
-
-			if (!intel_pll_is_valid(to_i915(dev), limit, &clock))
-				continue;
-
-			if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock,
-						best_error_ppm, &error_ppm))
-				continue;
-
-			*best_clock = clock;
-			best_error_ppm = error_ppm;
-			found = true;
-		}
-	}
-
-	return found;
-}
-
-bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,
-			struct dpll *best_clock)
-{
-	int refclk = 100000;
-	const struct intel_limit *limit = &intel_limits_bxt;
-
-	return chv_find_best_dpll(limit, crtc_state,
-				  crtc_state->port_clock, refclk,
-				  NULL, best_clock);
-}
-
 static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv,
 				    enum pipe pipe)
 {
@@ -5273,7 +4520,7 @@ static void ivb_update_fdi_bc_bifurcation(const struct intel_crtc_state *crtc_st
  * Finds the encoder associated with the given CRTC. This can only be
  * used when we know that the CRTC isn't feeding multiple encoders!
  */
-static struct intel_encoder *
+struct intel_encoder *
 intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
 			   const struct intel_crtc_state *crtc_state)
 {
@@ -7949,43 +7196,6 @@ static bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
-static u32 pnv_dpll_compute_fp(struct dpll *dpll)
-{
-	return (1 << dpll->n) << 16 | dpll->m2;
-}
-
-static u32 i9xx_dpll_compute_fp(struct dpll *dpll)
-{
-	return dpll->n << 16 | dpll->m1 << 8 | dpll->m2;
-}
-
-static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
-				     struct intel_crtc_state *crtc_state,
-				     struct dpll *reduced_clock)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	u32 fp, fp2 = 0;
-
-	if (IS_PINEVIEW(dev_priv)) {
-		fp = pnv_dpll_compute_fp(&crtc_state->dpll);
-		if (reduced_clock)
-			fp2 = pnv_dpll_compute_fp(reduced_clock);
-	} else {
-		fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
-		if (reduced_clock)
-			fp2 = i9xx_dpll_compute_fp(reduced_clock);
-	}
-
-	crtc_state->dpll_hw_state.fp0 = fp;
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-	    reduced_clock) {
-		crtc_state->dpll_hw_state.fp1 = fp2;
-	} else {
-		crtc_state->dpll_hw_state.fp1 = fp;
-	}
-}
-
 static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
 		pipe)
 {
@@ -8110,39 +7320,6 @@ void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state, enum link_m_n_s
 		intel_cpu_transcoder_set_m_n(crtc_state, dp_m_n, dp_m2_n2);
 }
 
-static void vlv_compute_dpll(struct intel_crtc *crtc,
-			     struct intel_crtc_state *pipe_config)
-{
-	pipe_config->dpll_hw_state.dpll = DPLL_INTEGRATED_REF_CLK_VLV |
-		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
-	if (crtc->pipe != PIPE_A)
-		pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
-
-	/* DPLL not used with DSI, but still need the rest set up */
-	if (!intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DSI))
-		pipe_config->dpll_hw_state.dpll |= DPLL_VCO_ENABLE |
-			DPLL_EXT_BUFFER_ENABLE_VLV;
-
-	pipe_config->dpll_hw_state.dpll_md =
-		(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-}
-
-static void chv_compute_dpll(struct intel_crtc *crtc,
-			     struct intel_crtc_state *pipe_config)
-{
-	pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV |
-		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
-	if (crtc->pipe != PIPE_A)
-		pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
-
-	/* DPLL not used with DSI, but still need the rest set up */
-	if (!intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DSI))
-		pipe_config->dpll_hw_state.dpll |= DPLL_VCO_ENABLE;
-
-	pipe_config->dpll_hw_state.dpll_md =
-		(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-}
-
 static void vlv_prepare_pll(struct intel_crtc *crtc,
 			    const struct intel_crtc_state *pipe_config)
 {
@@ -8402,128 +7579,7 @@ void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe)
 		vlv_disable_pll(dev_priv, pipe);
 }
 
-static void i9xx_compute_dpll(struct intel_crtc *crtc,
-			      struct intel_crtc_state *crtc_state,
-			      struct dpll *reduced_clock)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	u32 dpll;
-	struct dpll *clock = &crtc_state->dpll;
-
-	i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock);
-
-	dpll = DPLL_VGA_MODE_DIS;
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS))
-		dpll |= DPLLB_MODE_LVDS;
-	else
-		dpll |= DPLLB_MODE_DAC_SERIAL;
-
-	if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
-	    IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) {
-		dpll |= (crtc_state->pixel_multiplier - 1)
-			<< SDVO_MULTIPLIER_SHIFT_HIRES;
-	}
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO) ||
-	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
-		dpll |= DPLL_SDVO_HIGH_SPEED;
-
-	if (intel_crtc_has_dp_encoder(crtc_state))
-		dpll |= DPLL_SDVO_HIGH_SPEED;
-
-	/* compute bitmask from p1 value */
-	if (IS_PINEVIEW(dev_priv))
-		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
-	else {
-		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-		if (IS_G4X(dev_priv) && reduced_clock)
-			dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
-	}
-	switch (clock->p2) {
-	case 5:
-		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
-		break;
-	case 7:
-		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
-		break;
-	case 10:
-		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
-		break;
-	case 14:
-		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
-		break;
-	}
-	if (INTEL_GEN(dev_priv) >= 4)
-		dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
-
-	if (crtc_state->sdvo_tv_clock)
-		dpll |= PLL_REF_INPUT_TVCLKINBC;
-	else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-		 intel_panel_use_ssc(dev_priv))
-		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
-	else
-		dpll |= PLL_REF_INPUT_DREFCLK;
-
-	dpll |= DPLL_VCO_ENABLE;
-	crtc_state->dpll_hw_state.dpll = dpll;
-
-	if (INTEL_GEN(dev_priv) >= 4) {
-		u32 dpll_md = (crtc_state->pixel_multiplier - 1)
-			<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
-		crtc_state->dpll_hw_state.dpll_md = dpll_md;
-	}
-}
-
-static void i8xx_compute_dpll(struct intel_crtc *crtc,
-			      struct intel_crtc_state *crtc_state,
-			      struct dpll *reduced_clock)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	u32 dpll;
-	struct dpll *clock = &crtc_state->dpll;
-
-	i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock);
-
-	dpll = DPLL_VGA_MODE_DIS;
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-	} else {
-		if (clock->p1 == 2)
-			dpll |= PLL_P1_DIVIDE_BY_TWO;
-		else
-			dpll |= (clock->p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-		if (clock->p2 == 4)
-			dpll |= PLL_P2_DIVIDE_BY_4;
-	}
-
-	/*
-	 * Bspec:
-	 * "[Almador Errata}: For the correct operation of the muxed DVO pins
-	 *  (GDEVSELB/I2Cdata, GIRDBY/I2CClk) and (GFRAMEB/DVI_Data,
-	 *  GTRDYB/DVI_Clk): Bit 31 (DPLL VCO Enable) and Bit 30 (2X Clock
-	 *  Enable) must be set to “1” in both the DPLL A Control Register
-	 *  (06014h-06017h) and DPLL B Control Register (06018h-0601Bh)."
-	 *
-	 * For simplicity We simply keep both bits always enabled in
-	 * both DPLLS. The spec says we should disable the DVO 2X clock
-	 * when not needed, but this seems to work fine in practice.
-	 */
-	if (IS_I830(dev_priv) ||
-	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
-		dpll |= DPLL_DVO_2X_MODE;
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-	    intel_panel_use_ssc(dev_priv))
-		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
-	else
-		dpll |= PLL_REF_INPUT_DREFCLK;
 
-	dpll |= DPLL_VCO_ENABLE;
-	crtc_state->dpll_hw_state.dpll = dpll;
-}
 
 static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
 {
@@ -8729,207 +7785,6 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
 	intel_de_posting_read(dev_priv, PIPECONF(crtc->pipe));
 }
 
-static int i8xx_crtc_compute_clock(struct intel_crtc *crtc,
-				   struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	const struct intel_limit *limit;
-	int refclk = 48000;
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if (intel_panel_use_ssc(dev_priv)) {
-			refclk = dev_priv->vbt.lvds_ssc_freq;
-			drm_dbg_kms(&dev_priv->drm,
-				    "using SSC reference clock of %d kHz\n",
-				    refclk);
-		}
-
-		limit = &intel_limits_i8xx_lvds;
-	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO)) {
-		limit = &intel_limits_i8xx_dvo;
-	} else {
-		limit = &intel_limits_i8xx_dac;
-	}
-
-	if (!crtc_state->clock_set &&
-	    !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
-				 refclk, NULL, &crtc_state->dpll)) {
-		drm_err(&dev_priv->drm,
-			"Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
-	}
-
-	i8xx_compute_dpll(crtc, crtc_state, NULL);
-
-	return 0;
-}
-
-static int g4x_crtc_compute_clock(struct intel_crtc *crtc,
-				  struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	const struct intel_limit *limit;
-	int refclk = 96000;
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if (intel_panel_use_ssc(dev_priv)) {
-			refclk = dev_priv->vbt.lvds_ssc_freq;
-			drm_dbg_kms(&dev_priv->drm,
-				    "using SSC reference clock of %d kHz\n",
-				    refclk);
-		}
-
-		if (intel_is_dual_link_lvds(dev_priv))
-			limit = &intel_limits_g4x_dual_channel_lvds;
-		else
-			limit = &intel_limits_g4x_single_channel_lvds;
-	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) ||
-		   intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
-		limit = &intel_limits_g4x_hdmi;
-	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO)) {
-		limit = &intel_limits_g4x_sdvo;
-	} else {
-		/* The option is for other outputs */
-		limit = &intel_limits_i9xx_sdvo;
-	}
-
-	if (!crtc_state->clock_set &&
-	    !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
-				refclk, NULL, &crtc_state->dpll)) {
-		drm_err(&dev_priv->drm,
-			"Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
-	}
-
-	i9xx_compute_dpll(crtc, crtc_state, NULL);
-
-	return 0;
-}
-
-static int pnv_crtc_compute_clock(struct intel_crtc *crtc,
-				  struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	const struct intel_limit *limit;
-	int refclk = 96000;
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if (intel_panel_use_ssc(dev_priv)) {
-			refclk = dev_priv->vbt.lvds_ssc_freq;
-			drm_dbg_kms(&dev_priv->drm,
-				    "using SSC reference clock of %d kHz\n",
-				    refclk);
-		}
-
-		limit = &pnv_limits_lvds;
-	} else {
-		limit = &pnv_limits_sdvo;
-	}
-
-	if (!crtc_state->clock_set &&
-	    !pnv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
-				refclk, NULL, &crtc_state->dpll)) {
-		drm_err(&dev_priv->drm,
-			"Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
-	}
-
-	i9xx_compute_dpll(crtc, crtc_state, NULL);
-
-	return 0;
-}
-
-static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
-				   struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	const struct intel_limit *limit;
-	int refclk = 96000;
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if (intel_panel_use_ssc(dev_priv)) {
-			refclk = dev_priv->vbt.lvds_ssc_freq;
-			drm_dbg_kms(&dev_priv->drm,
-				    "using SSC reference clock of %d kHz\n",
-				    refclk);
-		}
-
-		limit = &intel_limits_i9xx_lvds;
-	} else {
-		limit = &intel_limits_i9xx_sdvo;
-	}
-
-	if (!crtc_state->clock_set &&
-	    !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
-				 refclk, NULL, &crtc_state->dpll)) {
-		drm_err(&dev_priv->drm,
-			"Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
-	}
-
-	i9xx_compute_dpll(crtc, crtc_state, NULL);
-
-	return 0;
-}
-
-static int chv_crtc_compute_clock(struct intel_crtc *crtc,
-				  struct intel_crtc_state *crtc_state)
-{
-	int refclk = 100000;
-	const struct intel_limit *limit = &intel_limits_chv;
-	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	if (!crtc_state->clock_set &&
-	    !chv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
-				refclk, NULL, &crtc_state->dpll)) {
-		drm_err(&i915->drm, "Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
-	}
-
-	chv_compute_dpll(crtc, crtc_state);
-
-	return 0;
-}
-
-static int vlv_crtc_compute_clock(struct intel_crtc *crtc,
-				  struct intel_crtc_state *crtc_state)
-{
-	int refclk = 100000;
-	const struct intel_limit *limit = &intel_limits_vlv;
-	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	if (!crtc_state->clock_set &&
-	    !vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
-				refclk, NULL, &crtc_state->dpll)) {
-		drm_err(&i915->drm,  "Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
-	}
-
-	vlv_compute_dpll(crtc, crtc_state);
-
-	return 0;
-}
 
 static bool i9xx_has_pfit(struct drm_i915_private *dev_priv)
 {
@@ -9940,172 +8795,6 @@ int ilk_get_lanes_required(int target_clock, int link_bw, int bpp)
 	return DIV_ROUND_UP(bps, link_bw * 8);
 }
 
-static bool ilk_needs_fb_cb_tune(struct dpll *dpll, int factor)
-{
-	return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
-}
-
-static void ilk_compute_dpll(struct intel_crtc *crtc,
-			     struct intel_crtc_state *crtc_state,
-			     struct dpll *reduced_clock)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	u32 dpll, fp, fp2;
-	int factor;
-
-	/* Enable autotuning of the PLL clock (if permissible) */
-	factor = 21;
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if ((intel_panel_use_ssc(dev_priv) &&
-		     dev_priv->vbt.lvds_ssc_freq == 100000) ||
-		    (HAS_PCH_IBX(dev_priv) &&
-		     intel_is_dual_link_lvds(dev_priv)))
-			factor = 25;
-	} else if (crtc_state->sdvo_tv_clock) {
-		factor = 20;
-	}
-
-	fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
-
-	if (ilk_needs_fb_cb_tune(&crtc_state->dpll, factor))
-		fp |= FP_CB_TUNE;
-
-	if (reduced_clock) {
-		fp2 = i9xx_dpll_compute_fp(reduced_clock);
-
-		if (reduced_clock->m < factor * reduced_clock->n)
-			fp2 |= FP_CB_TUNE;
-	} else {
-		fp2 = fp;
-	}
-
-	dpll = 0;
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS))
-		dpll |= DPLLB_MODE_LVDS;
-	else
-		dpll |= DPLLB_MODE_DAC_SERIAL;
-
-	dpll |= (crtc_state->pixel_multiplier - 1)
-		<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO) ||
-	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
-		dpll |= DPLL_SDVO_HIGH_SPEED;
-
-	if (intel_crtc_has_dp_encoder(crtc_state))
-		dpll |= DPLL_SDVO_HIGH_SPEED;
-
-	/*
-	 * The high speed IO clock is only really required for
-	 * SDVO/HDMI/DP, but we also enable it for CRT to make it
-	 * possible to share the DPLL between CRT and HDMI. Enabling
-	 * the clock needlessly does no real harm, except use up a
-	 * bit of power potentially.
-	 *
-	 * We'll limit this to IVB with 3 pipes, since it has only two
-	 * DPLLs and so DPLL sharing is the only way to get three pipes
-	 * driving PCH ports at the same time. On SNB we could do this,
-	 * and potentially avoid enabling the second DPLL, but it's not
-	 * clear if it''s a win or loss power wise. No point in doing
-	 * this on ILK at all since it has a fixed DPLL<->pipe mapping.
-	 */
-	if (INTEL_NUM_PIPES(dev_priv) == 3 &&
-	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG))
-		dpll |= DPLL_SDVO_HIGH_SPEED;
-
-	/* compute bitmask from p1 value */
-	dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-	/* also FPA1 */
-	dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
-
-	switch (crtc_state->dpll.p2) {
-	case 5:
-		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
-		break;
-	case 7:
-		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
-		break;
-	case 10:
-		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
-		break;
-	case 14:
-		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
-		break;
-	}
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-	    intel_panel_use_ssc(dev_priv))
-		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
-	else
-		dpll |= PLL_REF_INPUT_DREFCLK;
-
-	dpll |= DPLL_VCO_ENABLE;
-
-	crtc_state->dpll_hw_state.dpll = dpll;
-	crtc_state->dpll_hw_state.fp0 = fp;
-	crtc_state->dpll_hw_state.fp1 = fp2;
-}
-
-static int ilk_crtc_compute_clock(struct intel_crtc *crtc,
-				  struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct intel_atomic_state *state =
-		to_intel_atomic_state(crtc_state->uapi.state);
-	const struct intel_limit *limit;
-	int refclk = 120000;
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
-	if (!crtc_state->has_pch_encoder)
-		return 0;
-
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if (intel_panel_use_ssc(dev_priv)) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "using SSC reference clock of %d kHz\n",
-				    dev_priv->vbt.lvds_ssc_freq);
-			refclk = dev_priv->vbt.lvds_ssc_freq;
-		}
-
-		if (intel_is_dual_link_lvds(dev_priv)) {
-			if (refclk == 100000)
-				limit = &ilk_limits_dual_lvds_100m;
-			else
-				limit = &ilk_limits_dual_lvds;
-		} else {
-			if (refclk == 100000)
-				limit = &ilk_limits_single_lvds_100m;
-			else
-				limit = &ilk_limits_single_lvds;
-		}
-	} else {
-		limit = &ilk_limits_dac;
-	}
-
-	if (!crtc_state->clock_set &&
-	    !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
-				refclk, NULL, &crtc_state->dpll)) {
-		drm_err(&dev_priv->drm,
-			"Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
-	}
-
-	ilk_compute_dpll(crtc, crtc_state, NULL);
-
-	if (!intel_reserve_shared_dplls(state, crtc, NULL)) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "failed to find PLL for pipe %c\n",
-			    pipe_name(crtc->pipe));
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc,
 					 struct intel_link_m_n *m_n)
 {
@@ -10518,29 +9207,6 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
 	return ret;
 }
 
-static int hsw_crtc_compute_clock(struct intel_crtc *crtc,
-				  struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct intel_atomic_state *state =
-		to_intel_atomic_state(crtc_state->uapi.state);
-
-	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
-	    INTEL_GEN(dev_priv) >= 11) {
-		struct intel_encoder *encoder =
-			intel_get_crtc_new_encoder(state, crtc_state);
-
-		if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "failed to find PLL for pipe %c\n",
-				    pipe_name(crtc->pipe));
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
 static void dg1_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port,
 			    struct intel_crtc_state *pipe_config)
 {
@@ -16475,69 +15141,27 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 {
 	intel_init_cdclk_hooks(dev_priv);
 
+	intel_init_clock_hook(dev_priv);
+
 	if (INTEL_GEN(dev_priv) >= 9) {
 		dev_priv->display.get_pipe_config = hsw_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			skl_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = hsw_crtc_compute_clock;
 		dev_priv->display.crtc_enable = hsw_crtc_enable;
 		dev_priv->display.crtc_disable = hsw_crtc_disable;
 	} else if (HAS_DDI(dev_priv)) {
 		dev_priv->display.get_pipe_config = hsw_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock =
-			hsw_crtc_compute_clock;
 		dev_priv->display.crtc_enable = hsw_crtc_enable;
 		dev_priv->display.crtc_disable = hsw_crtc_disable;
 	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		dev_priv->display.get_pipe_config = ilk_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock =
-			ilk_crtc_compute_clock;
 		dev_priv->display.crtc_enable = ilk_crtc_enable;
 		dev_priv->display.crtc_disable = ilk_crtc_disable;
-	} else if (IS_CHERRYVIEW(dev_priv)) {
-		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = chv_crtc_compute_clock;
-		dev_priv->display.crtc_enable = valleyview_crtc_enable;
-		dev_priv->display.crtc_disable = i9xx_crtc_disable;
-	} else if (IS_VALLEYVIEW(dev_priv)) {
+	} else if (IS_CHERRYVIEW(dev_priv) ||
+		   IS_VALLEYVIEW(dev_priv)) {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = vlv_crtc_compute_clock;
 		dev_priv->display.crtc_enable = valleyview_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
-	} else if (IS_G4X(dev_priv)) {
-		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock;
-		dev_priv->display.crtc_enable = i9xx_crtc_enable;
-		dev_priv->display.crtc_disable = i9xx_crtc_disable;
-	} else if (IS_PINEVIEW(dev_priv)) {
-		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock;
-		dev_priv->display.crtc_enable = i9xx_crtc_enable;
-		dev_priv->display.crtc_disable = i9xx_crtc_disable;
-	} else if (!IS_GEN(dev_priv, 2)) {
-		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
-		dev_priv->display.crtc_enable = i9xx_crtc_enable;
-		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 	} else {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
-		dev_priv->display.get_initial_plane_config =
-			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock;
 		dev_priv->display.crtc_enable = i9xx_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 	}
@@ -16551,10 +15175,13 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 		dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
 	}
 
-	if (INTEL_GEN(dev_priv) >= 9)
+	if (INTEL_GEN(dev_priv) >= 9) {
 		dev_priv->display.commit_modeset_enables = skl_commit_modeset_enables;
-	else
+		dev_priv->display.get_initial_plane_config = skl_get_initial_plane_config;
+	} else {
 		dev_priv->display.commit_modeset_enables = intel_commit_modeset_enables;
+		dev_priv->display.get_initial_plane_config = i9xx_get_initial_plane_config;
+	}
 
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 0eba91d18e96..f1e36cca86c1 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -653,7 +653,9 @@ u32 intel_plane_compute_aligned_offset(int *x, int *y,
 				       int color_plane);
 int intel_plane_pin_fb(struct intel_plane_state *plane_state);
 void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
-
+struct intel_encoder *
+intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
+			   const struct intel_crtc_state *crtc_state);
 /* cursor */
 struct intel_plane *
 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
@@ -665,6 +667,15 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
 struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
 void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
 			    struct intel_crtc *crtc);
+/* clock */
+void intel_init_clock_hook(struct drm_i915_private *dev_priv);
+int vlv_calc_dpll_params(int refclk, struct dpll *clock);
+int pnv_calc_dpll_params(int refclk, struct dpll *clock);
+int i9xx_calc_dpll_params(int refclk, struct dpll *clock);
+void vlv_compute_dpll(struct intel_crtc *crtc,
+		      struct intel_crtc_state *pipe_config);
+void chv_compute_dpll(struct intel_crtc *crtc,
+		      struct intel_crtc_state *pipe_config);
 
 /* modesetting */
 void intel_modeset_init_hw(struct drm_i915_private *i915);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index dfe573c8b5ae..5d015b0710f2 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1811,4 +1811,9 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
 	return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
 }
 
+static inline u32 i9xx_dpll_compute_fp(struct dpll *dpll)
+{
+	return dpll->n << 16 | dpll->m1 << 8 | dpll->m2;
+}
+
 #endif /*  __INTEL_DISPLAY_TYPES_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_legacy.c b/drivers/gpu/drm/i915/display/intel_dpll_legacy.c
new file mode 100644
index 000000000000..75819c1da039
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dpll_legacy.c
@@ -0,0 +1,1370 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#include <linux/kernel.h>
+#include "intel_display_types.h"
+#include "intel_display.h"
+#include "intel_lvds.h"
+#include "intel_panel.h"
+
+static bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
+{
+	if (dev_priv->params.panel_use_ssc >= 0)
+		return dev_priv->params.panel_use_ssc != 0;
+	return dev_priv->vbt.lvds_use_ssc
+		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
+}
+
+struct intel_limit {
+	struct {
+		int min, max;
+	} dot, vco, n, m, m1, m2, p, p1;
+
+	struct {
+		int dot_limit;
+		int p2_slow, p2_fast;
+	} p2;
+};
+static const struct intel_limit intel_limits_i8xx_dac = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 908000, .max = 1512000 },
+	.n = { .min = 2, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 2, .max = 33 },
+	.p2 = { .dot_limit = 165000,
+		.p2_slow = 4, .p2_fast = 2 },
+};
+
+static const struct intel_limit intel_limits_i8xx_dvo = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 908000, .max = 1512000 },
+	.n = { .min = 2, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 2, .max = 33 },
+	.p2 = { .dot_limit = 165000,
+		.p2_slow = 4, .p2_fast = 4 },
+};
+
+static const struct intel_limit intel_limits_i8xx_lvds = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 908000, .max = 1512000 },
+	.n = { .min = 2, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 1, .max = 6 },
+	.p2 = { .dot_limit = 165000,
+		.p2_slow = 14, .p2_fast = 7 },
+};
+
+static const struct intel_limit intel_limits_i9xx_sdvo = {
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1400000, .max = 2800000 },
+	.n = { .min = 1, .max = 6 },
+	.m = { .min = 70, .max = 120 },
+	.m1 = { .min = 8, .max = 18 },
+	.m2 = { .min = 3, .max = 7 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8 },
+	.p2 = { .dot_limit = 200000,
+		.p2_slow = 10, .p2_fast = 5 },
+};
+
+static const struct intel_limit intel_limits_i9xx_lvds = {
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1400000, .max = 2800000 },
+	.n = { .min = 1, .max = 6 },
+	.m = { .min = 70, .max = 120 },
+	.m1 = { .min = 8, .max = 18 },
+	.m2 = { .min = 3, .max = 7 },
+	.p = { .min = 7, .max = 98 },
+	.p1 = { .min = 1, .max = 8 },
+	.p2 = { .dot_limit = 112000,
+		.p2_slow = 14, .p2_fast = 7 },
+};
+
+
+static const struct intel_limit intel_limits_g4x_sdvo = {
+	.dot = { .min = 25000, .max = 270000 },
+	.vco = { .min = 1750000, .max = 3500000},
+	.n = { .min = 1, .max = 4 },
+	.m = { .min = 104, .max = 138 },
+	.m1 = { .min = 17, .max = 23 },
+	.m2 = { .min = 5, .max = 11 },
+	.p = { .min = 10, .max = 30 },
+	.p1 = { .min = 1, .max = 3},
+	.p2 = { .dot_limit = 270000,
+		.p2_slow = 10,
+		.p2_fast = 10
+	},
+};
+
+static const struct intel_limit intel_limits_g4x_hdmi = {
+	.dot = { .min = 22000, .max = 400000 },
+	.vco = { .min = 1750000, .max = 3500000},
+	.n = { .min = 1, .max = 4 },
+	.m = { .min = 104, .max = 138 },
+	.m1 = { .min = 16, .max = 23 },
+	.m2 = { .min = 5, .max = 11 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8},
+	.p2 = { .dot_limit = 165000,
+		.p2_slow = 10, .p2_fast = 5 },
+};
+
+static const struct intel_limit intel_limits_g4x_single_channel_lvds = {
+	.dot = { .min = 20000, .max = 115000 },
+	.vco = { .min = 1750000, .max = 3500000 },
+	.n = { .min = 1, .max = 3 },
+	.m = { .min = 104, .max = 138 },
+	.m1 = { .min = 17, .max = 23 },
+	.m2 = { .min = 5, .max = 11 },
+	.p = { .min = 28, .max = 112 },
+	.p1 = { .min = 2, .max = 8 },
+	.p2 = { .dot_limit = 0,
+		.p2_slow = 14, .p2_fast = 14
+	},
+};
+
+static const struct intel_limit intel_limits_g4x_dual_channel_lvds = {
+	.dot = { .min = 80000, .max = 224000 },
+	.vco = { .min = 1750000, .max = 3500000 },
+	.n = { .min = 1, .max = 3 },
+	.m = { .min = 104, .max = 138 },
+	.m1 = { .min = 17, .max = 23 },
+	.m2 = { .min = 5, .max = 11 },
+	.p = { .min = 14, .max = 42 },
+	.p1 = { .min = 2, .max = 6 },
+	.p2 = { .dot_limit = 0,
+		.p2_slow = 7, .p2_fast = 7
+	},
+};
+
+static const struct intel_limit pnv_limits_sdvo = {
+	.dot = { .min = 20000, .max = 400000},
+	.vco = { .min = 1700000, .max = 3500000 },
+	/* Pineview's Ncounter is a ring counter */
+	.n = { .min = 3, .max = 6 },
+	.m = { .min = 2, .max = 256 },
+	/* Pineview only has one combined m divider, which we treat as m2. */
+	.m1 = { .min = 0, .max = 0 },
+	.m2 = { .min = 0, .max = 254 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8 },
+	.p2 = { .dot_limit = 200000,
+		.p2_slow = 10, .p2_fast = 5 },
+};
+
+static const struct intel_limit pnv_limits_lvds = {
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1700000, .max = 3500000 },
+	.n = { .min = 3, .max = 6 },
+	.m = { .min = 2, .max = 256 },
+	.m1 = { .min = 0, .max = 0 },
+	.m2 = { .min = 0, .max = 254 },
+	.p = { .min = 7, .max = 112 },
+	.p1 = { .min = 1, .max = 8 },
+	.p2 = { .dot_limit = 112000,
+		.p2_slow = 14, .p2_fast = 14 },
+};
+
+/* Ironlake / Sandybridge
+ *
+ * We calculate clock using (register_value + 2) for N/M1/M2, so here
+ * the range value for them is (actual_value - 2).
+ */
+static const struct intel_limit ilk_limits_dac = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 1760000, .max = 3510000 },
+	.n = { .min = 1, .max = 5 },
+	.m = { .min = 79, .max = 127 },
+	.m1 = { .min = 12, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8 },
+	.p2 = { .dot_limit = 225000,
+		.p2_slow = 10, .p2_fast = 5 },
+};
+
+static const struct intel_limit ilk_limits_single_lvds = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 1760000, .max = 3510000 },
+	.n = { .min = 1, .max = 3 },
+	.m = { .min = 79, .max = 118 },
+	.m1 = { .min = 12, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 28, .max = 112 },
+	.p1 = { .min = 2, .max = 8 },
+	.p2 = { .dot_limit = 225000,
+		.p2_slow = 14, .p2_fast = 14 },
+};
+
+static const struct intel_limit ilk_limits_dual_lvds = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 1760000, .max = 3510000 },
+	.n = { .min = 1, .max = 3 },
+	.m = { .min = 79, .max = 127 },
+	.m1 = { .min = 12, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 14, .max = 56 },
+	.p1 = { .min = 2, .max = 8 },
+	.p2 = { .dot_limit = 225000,
+		.p2_slow = 7, .p2_fast = 7 },
+};
+
+/* LVDS 100mhz refclk limits. */
+static const struct intel_limit ilk_limits_single_lvds_100m = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 1760000, .max = 3510000 },
+	.n = { .min = 1, .max = 2 },
+	.m = { .min = 79, .max = 126 },
+	.m1 = { .min = 12, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 28, .max = 112 },
+	.p1 = { .min = 2, .max = 8 },
+	.p2 = { .dot_limit = 225000,
+		.p2_slow = 14, .p2_fast = 14 },
+};
+
+static const struct intel_limit ilk_limits_dual_lvds_100m = {
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 1760000, .max = 3510000 },
+	.n = { .min = 1, .max = 3 },
+	.m = { .min = 79, .max = 126 },
+	.m1 = { .min = 12, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 14, .max = 42 },
+	.p1 = { .min = 2, .max = 6 },
+	.p2 = { .dot_limit = 225000,
+		.p2_slow = 7, .p2_fast = 7 },
+};
+
+static const struct intel_limit intel_limits_vlv = {
+	 /*
+	  * These are the data rate limits (measured in fast clocks)
+	  * since those are the strictest limits we have. The fast
+	  * clock and actual rate limits are more relaxed, so checking
+	  * them would make no difference.
+	  */
+	.dot = { .min = 25000 * 5, .max = 270000 * 5 },
+	.vco = { .min = 4000000, .max = 6000000 },
+	.n = { .min = 1, .max = 7 },
+	.m1 = { .min = 2, .max = 3 },
+	.m2 = { .min = 11, .max = 156 },
+	.p1 = { .min = 2, .max = 3 },
+	.p2 = { .p2_slow = 2, .p2_fast = 20 }, /* slow=min, fast=max */
+};
+
+static const struct intel_limit intel_limits_chv = {
+	/*
+	 * These are the data rate limits (measured in fast clocks)
+	 * since those are the strictest limits we have.  The fast
+	 * clock and actual rate limits are more relaxed, so checking
+	 * them would make no difference.
+	 */
+	.dot = { .min = 25000 * 5, .max = 540000 * 5},
+	.vco = { .min = 4800000, .max = 6480000 },
+	.n = { .min = 1, .max = 1 },
+	.m1 = { .min = 2, .max = 2 },
+	.m2 = { .min = 24 << 22, .max = 175 << 22 },
+	.p1 = { .min = 2, .max = 4 },
+	.p2 = {	.p2_slow = 1, .p2_fast = 14 },
+};
+
+static const struct intel_limit intel_limits_bxt = {
+	/* FIXME: find real dot limits */
+	.dot = { .min = 0, .max = INT_MAX },
+	.vco = { .min = 4800000, .max = 6700000 },
+	.n = { .min = 1, .max = 1 },
+	.m1 = { .min = 2, .max = 2 },
+	/* FIXME: find real m2 limits */
+	.m2 = { .min = 2 << 22, .max = 255 << 22 },
+	.p1 = { .min = 2, .max = 4 },
+	.p2 = { .p2_slow = 1, .p2_fast = 20 },
+};
+
+/*
+ * Platform specific helpers to calculate the port PLL loopback- (clock.m),
+ * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
+ * (clock.dot) clock rates. This fast dot clock is fed to the port's IO logic.
+ * The helpers' return value is the rate of the clock that is fed to the
+ * display engine's pipe which can be the above fast dot clock rate or a
+ * divided-down version of it.
+ */
+/* m1 is reserved as 0 in Pineview, n is a ring counter */
+int pnv_calc_dpll_params(int refclk, struct dpll *clock)
+{
+	clock->m = clock->m2 + 2;
+	clock->p = clock->p1 * clock->p2;
+	if (WARN_ON(clock->n == 0 || clock->p == 0))
+		return 0;
+	clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
+	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+	return clock->dot;
+}
+
+static u32 i9xx_dpll_compute_m(struct dpll *dpll)
+{
+	return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
+}
+
+int i9xx_calc_dpll_params(int refclk, struct dpll *clock)
+{
+	clock->m = i9xx_dpll_compute_m(clock);
+	clock->p = clock->p1 * clock->p2;
+	if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
+		return 0;
+	clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
+	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+	return clock->dot;
+}
+
+int vlv_calc_dpll_params(int refclk, struct dpll *clock)
+{
+	clock->m = clock->m1 * clock->m2;
+	clock->p = clock->p1 * clock->p2;
+	if (WARN_ON(clock->n == 0 || clock->p == 0))
+		return 0;
+	clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
+	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+	return clock->dot / 5;
+}
+
+int chv_calc_dpll_params(int refclk, struct dpll *clock)
+{
+	clock->m = clock->m1 * clock->m2;
+	clock->p = clock->p1 * clock->p2;
+	if (WARN_ON(clock->n == 0 || clock->p == 0))
+		return 0;
+	clock->vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m),
+					   clock->n << 22);
+	clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+	return clock->dot / 5;
+}
+
+/*
+ * Returns whether the given set of divisors are valid for a given refclk with
+ * the given connectors.
+ */
+static bool intel_pll_is_valid(struct drm_i915_private *dev_priv,
+			       const struct intel_limit *limit,
+			       const struct dpll *clock)
+{
+	if (clock->n < limit->n.min || limit->n.max < clock->n)
+		return false;
+	if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
+		return false;
+	if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
+		return false;
+	if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
+		return false;
+
+	if (!IS_PINEVIEW(dev_priv) && !IS_VALLEYVIEW(dev_priv) &&
+	    !IS_CHERRYVIEW(dev_priv) && !IS_GEN9_LP(dev_priv))
+		if (clock->m1 <= clock->m2)
+			return false;
+
+	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
+	    !IS_GEN9_LP(dev_priv)) {
+		if (clock->p < limit->p.min || limit->p.max < clock->p)
+			return false;
+		if (clock->m < limit->m.min || limit->m.max < clock->m)
+			return false;
+	}
+
+	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+		return false;
+	/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
+	 * connector, etc., rather than just a single range.
+	 */
+	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+		return false;
+
+	return true;
+}
+
+static int
+i9xx_select_p2_div(const struct intel_limit *limit,
+		   const struct intel_crtc_state *crtc_state,
+		   int target)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		/*
+		 * For LVDS just rely on its current settings for dual-channel.
+		 * We haven't figured out how to reliably set up different
+		 * single/dual channel state, if we even can.
+		 */
+		if (intel_is_dual_link_lvds(dev_priv))
+			return limit->p2.p2_fast;
+		else
+			return limit->p2.p2_slow;
+	} else {
+		if (target < limit->p2.dot_limit)
+			return limit->p2.p2_slow;
+		else
+			return limit->p2.p2_fast;
+	}
+}
+
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
+static bool
+i9xx_find_best_dpll(const struct intel_limit *limit,
+		    struct intel_crtc_state *crtc_state,
+		    int target, int refclk, struct dpll *match_clock,
+		    struct dpll *best_clock)
+{
+	struct drm_device *dev = crtc_state->uapi.crtc->dev;
+	struct dpll clock;
+	int err = target;
+
+	memset(best_clock, 0, sizeof(*best_clock));
+
+	clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
+
+	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
+	     clock.m1++) {
+		for (clock.m2 = limit->m2.min;
+		     clock.m2 <= limit->m2.max; clock.m2++) {
+			if (clock.m2 >= clock.m1)
+				break;
+			for (clock.n = limit->n.min;
+			     clock.n <= limit->n.max; clock.n++) {
+				for (clock.p1 = limit->p1.min;
+					clock.p1 <= limit->p1.max; clock.p1++) {
+					int this_err;
+
+					i9xx_calc_dpll_params(refclk, &clock);
+					if (!intel_pll_is_valid(to_i915(dev),
+								limit,
+								&clock))
+						continue;
+					if (match_clock &&
+					    clock.p != match_clock->p)
+						continue;
+
+					this_err = abs(clock.dot - target);
+					if (this_err < err) {
+						*best_clock = clock;
+						err = this_err;
+					}
+				}
+			}
+		}
+	}
+
+	return (err != target);
+}
+
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
+static bool
+pnv_find_best_dpll(const struct intel_limit *limit,
+		   struct intel_crtc_state *crtc_state,
+		   int target, int refclk, struct dpll *match_clock,
+		   struct dpll *best_clock)
+{
+	struct drm_device *dev = crtc_state->uapi.crtc->dev;
+	struct dpll clock;
+	int err = target;
+
+	memset(best_clock, 0, sizeof(*best_clock));
+
+	clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
+
+	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
+	     clock.m1++) {
+		for (clock.m2 = limit->m2.min;
+		     clock.m2 <= limit->m2.max; clock.m2++) {
+			for (clock.n = limit->n.min;
+			     clock.n <= limit->n.max; clock.n++) {
+				for (clock.p1 = limit->p1.min;
+					clock.p1 <= limit->p1.max; clock.p1++) {
+					int this_err;
+
+					pnv_calc_dpll_params(refclk, &clock);
+					if (!intel_pll_is_valid(to_i915(dev),
+								limit,
+								&clock))
+						continue;
+					if (match_clock &&
+					    clock.p != match_clock->p)
+						continue;
+
+					this_err = abs(clock.dot - target);
+					if (this_err < err) {
+						*best_clock = clock;
+						err = this_err;
+					}
+				}
+			}
+		}
+	}
+
+	return (err != target);
+}
+
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
+static bool
+g4x_find_best_dpll(const struct intel_limit *limit,
+		   struct intel_crtc_state *crtc_state,
+		   int target, int refclk, struct dpll *match_clock,
+		   struct dpll *best_clock)
+{
+	struct drm_device *dev = crtc_state->uapi.crtc->dev;
+	struct dpll clock;
+	int max_n;
+	bool found = false;
+	/* approximately equals target * 0.00585 */
+	int err_most = (target >> 8) + (target >> 9);
+
+	memset(best_clock, 0, sizeof(*best_clock));
+
+	clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
+
+	max_n = limit->n.max;
+	/* based on hardware requirement, prefer smaller n to precision */
+	for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
+		/* based on hardware requirement, prefere larger m1,m2 */
+		for (clock.m1 = limit->m1.max;
+		     clock.m1 >= limit->m1.min; clock.m1--) {
+			for (clock.m2 = limit->m2.max;
+			     clock.m2 >= limit->m2.min; clock.m2--) {
+				for (clock.p1 = limit->p1.max;
+				     clock.p1 >= limit->p1.min; clock.p1--) {
+					int this_err;
+
+					i9xx_calc_dpll_params(refclk, &clock);
+					if (!intel_pll_is_valid(to_i915(dev),
+								limit,
+								&clock))
+						continue;
+
+					this_err = abs(clock.dot - target);
+					if (this_err < err_most) {
+						*best_clock = clock;
+						err_most = this_err;
+						max_n = clock.n;
+						found = true;
+					}
+				}
+			}
+		}
+	}
+	return found;
+}
+
+/*
+ * Check if the calculated PLL configuration is more optimal compared to the
+ * best configuration and error found so far. Return the calculated error.
+ */
+static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
+			       const struct dpll *calculated_clock,
+			       const struct dpll *best_clock,
+			       unsigned int best_error_ppm,
+			       unsigned int *error_ppm)
+{
+	/*
+	 * For CHV ignore the error and consider only the P value.
+	 * Prefer a bigger P value based on HW requirements.
+	 */
+	if (IS_CHERRYVIEW(to_i915(dev))) {
+		*error_ppm = 0;
+
+		return calculated_clock->p > best_clock->p;
+	}
+
+	if (drm_WARN_ON_ONCE(dev, !target_freq))
+		return false;
+
+	*error_ppm = div_u64(1000000ULL *
+				abs(target_freq - calculated_clock->dot),
+			     target_freq);
+	/*
+	 * Prefer a better P value over a better (smaller) error if the error
+	 * is small. Ensure this preference for future configurations too by
+	 * setting the error to 0.
+	 */
+	if (*error_ppm < 100 && calculated_clock->p > best_clock->p) {
+		*error_ppm = 0;
+
+		return true;
+	}
+
+	return *error_ppm + 10 < best_error_ppm;
+}
+
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
+static bool
+vlv_find_best_dpll(const struct intel_limit *limit,
+		   struct intel_crtc_state *crtc_state,
+		   int target, int refclk, struct dpll *match_clock,
+		   struct dpll *best_clock)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_device *dev = crtc->base.dev;
+	struct dpll clock;
+	unsigned int bestppm = 1000000;
+	/* min update 19.2 MHz */
+	int max_n = min(limit->n.max, refclk / 19200);
+	bool found = false;
+
+	target *= 5; /* fast clock */
+
+	memset(best_clock, 0, sizeof(*best_clock));
+
+	/* based on hardware requirement, prefer smaller n to precision */
+	for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
+		for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
+			for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow;
+			     clock.p2 -= clock.p2 > 10 ? 2 : 1) {
+				clock.p = clock.p1 * clock.p2;
+				/* based on hardware requirement, prefer bigger m1,m2 values */
+				for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
+					unsigned int ppm;
+
+					clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n,
+								     refclk * clock.m1);
+
+					vlv_calc_dpll_params(refclk, &clock);
+
+					if (!intel_pll_is_valid(to_i915(dev),
+								limit,
+								&clock))
+						continue;
+
+					if (!vlv_PLL_is_optimal(dev, target,
+								&clock,
+								best_clock,
+								bestppm, &ppm))
+						continue;
+
+					*best_clock = clock;
+					bestppm = ppm;
+					found = true;
+				}
+			}
+		}
+	}
+
+	return found;
+}
+
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
+static bool
+chv_find_best_dpll(const struct intel_limit *limit,
+		   struct intel_crtc_state *crtc_state,
+		   int target, int refclk, struct dpll *match_clock,
+		   struct dpll *best_clock)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_device *dev = crtc->base.dev;
+	unsigned int best_error_ppm;
+	struct dpll clock;
+	u64 m2;
+	int found = false;
+
+	memset(best_clock, 0, sizeof(*best_clock));
+	best_error_ppm = 1000000;
+
+	/*
+	 * Based on hardware doc, the n always set to 1, and m1 always
+	 * set to 2.  If requires to support 200Mhz refclk, we need to
+	 * revisit this because n may not 1 anymore.
+	 */
+	clock.n = 1;
+	clock.m1 = 2;
+	target *= 5;	/* fast clock */
+
+	for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
+		for (clock.p2 = limit->p2.p2_fast;
+				clock.p2 >= limit->p2.p2_slow;
+				clock.p2 -= clock.p2 > 10 ? 2 : 1) {
+			unsigned int error_ppm;
+
+			clock.p = clock.p1 * clock.p2;
+
+			m2 = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(target, clock.p * clock.n) << 22,
+						   refclk * clock.m1);
+
+			if (m2 > INT_MAX/clock.m1)
+				continue;
+
+			clock.m2 = m2;
+
+			chv_calc_dpll_params(refclk, &clock);
+
+			if (!intel_pll_is_valid(to_i915(dev), limit, &clock))
+				continue;
+
+			if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock,
+						best_error_ppm, &error_ppm))
+				continue;
+
+			*best_clock = clock;
+			best_error_ppm = error_ppm;
+			found = true;
+		}
+	}
+
+	return found;
+}
+
+bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,
+			struct dpll *best_clock)
+{
+	int refclk = 100000;
+	const struct intel_limit *limit = &intel_limits_bxt;
+
+	return chv_find_best_dpll(limit, crtc_state,
+				  crtc_state->port_clock, refclk,
+				  NULL, best_clock);
+}
+
+static u32 pnv_dpll_compute_fp(struct dpll *dpll)
+{
+	return (1 << dpll->n) << 16 | dpll->m2;
+}
+
+static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
+				     struct intel_crtc_state *crtc_state,
+				     struct dpll *reduced_clock)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	u32 fp, fp2 = 0;
+
+	if (IS_PINEVIEW(dev_priv)) {
+		fp = pnv_dpll_compute_fp(&crtc_state->dpll);
+		if (reduced_clock)
+			fp2 = pnv_dpll_compute_fp(reduced_clock);
+	} else {
+		fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
+		if (reduced_clock)
+			fp2 = i9xx_dpll_compute_fp(reduced_clock);
+	}
+
+	crtc_state->dpll_hw_state.fp0 = fp;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+	    reduced_clock) {
+		crtc_state->dpll_hw_state.fp1 = fp2;
+	} else {
+		crtc_state->dpll_hw_state.fp1 = fp;
+	}
+}
+
+static void i9xx_compute_dpll(struct intel_crtc *crtc,
+			      struct intel_crtc_state *crtc_state,
+			      struct dpll *reduced_clock)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	u32 dpll;
+	struct dpll *clock = &crtc_state->dpll;
+
+	i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock);
+
+	dpll = DPLL_VGA_MODE_DIS;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS))
+		dpll |= DPLLB_MODE_LVDS;
+	else
+		dpll |= DPLLB_MODE_DAC_SERIAL;
+
+	if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
+	    IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) {
+		dpll |= (crtc_state->pixel_multiplier - 1)
+			<< SDVO_MULTIPLIER_SHIFT_HIRES;
+	}
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO) ||
+	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+		dpll |= DPLL_SDVO_HIGH_SPEED;
+
+	if (intel_crtc_has_dp_encoder(crtc_state))
+		dpll |= DPLL_SDVO_HIGH_SPEED;
+
+	/* compute bitmask from p1 value */
+	if (IS_PINEVIEW(dev_priv))
+		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
+	else {
+		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+		if (IS_G4X(dev_priv) && reduced_clock)
+			dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
+	}
+	switch (clock->p2) {
+	case 5:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+		break;
+	case 7:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+		break;
+	case 10:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+		break;
+	case 14:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+		break;
+	}
+	if (INTEL_GEN(dev_priv) >= 4)
+		dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
+
+	if (crtc_state->sdvo_tv_clock)
+		dpll |= PLL_REF_INPUT_TVCLKINBC;
+	else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+		 intel_panel_use_ssc(dev_priv))
+		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+	else
+		dpll |= PLL_REF_INPUT_DREFCLK;
+
+	dpll |= DPLL_VCO_ENABLE;
+	crtc_state->dpll_hw_state.dpll = dpll;
+
+	if (INTEL_GEN(dev_priv) >= 4) {
+		u32 dpll_md = (crtc_state->pixel_multiplier - 1)
+			<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
+		crtc_state->dpll_hw_state.dpll_md = dpll_md;
+	}
+}
+
+static void i8xx_compute_dpll(struct intel_crtc *crtc,
+			      struct intel_crtc_state *crtc_state,
+			      struct dpll *reduced_clock)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	u32 dpll;
+	struct dpll *clock = &crtc_state->dpll;
+
+	i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock);
+
+	dpll = DPLL_VGA_MODE_DIS;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+	} else {
+		if (clock->p1 == 2)
+			dpll |= PLL_P1_DIVIDE_BY_TWO;
+		else
+			dpll |= (clock->p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+		if (clock->p2 == 4)
+			dpll |= PLL_P2_DIVIDE_BY_4;
+	}
+
+	/*
+	 * Bspec:
+	 * "[Almador Errata}: For the correct operation of the muxed DVO pins
+	 *  (GDEVSELB/I2Cdata, GIRDBY/I2CClk) and (GFRAMEB/DVI_Data,
+	 *  GTRDYB/DVI_Clk): Bit 31 (DPLL VCO Enable) and Bit 30 (2X Clock
+	 *  Enable) must be set to “1” in both the DPLL A Control Register
+	 *  (06014h-06017h) and DPLL B Control Register (06018h-0601Bh)."
+	 *
+	 * For simplicity We simply keep both bits always enabled in
+	 * both DPLLS. The spec says we should disable the DVO 2X clock
+	 * when not needed, but this seems to work fine in practice.
+	 */
+	if (IS_I830(dev_priv) ||
+	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
+		dpll |= DPLL_DVO_2X_MODE;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+	    intel_panel_use_ssc(dev_priv))
+		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+	else
+		dpll |= PLL_REF_INPUT_DREFCLK;
+
+	dpll |= DPLL_VCO_ENABLE;
+	crtc_state->dpll_hw_state.dpll = dpll;
+}
+
+static int hsw_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_atomic_state *state =
+		to_intel_atomic_state(crtc_state->uapi.state);
+
+	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
+	    INTEL_GEN(dev_priv) >= 11) {
+		struct intel_encoder *encoder =
+			intel_get_crtc_new_encoder(state, crtc_state);
+
+		if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "failed to find PLL for pipe %c\n",
+				    pipe_name(crtc->pipe));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static bool ilk_needs_fb_cb_tune(struct dpll *dpll, int factor)
+{
+	return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
+}
+
+
+static void ilk_compute_dpll(struct intel_crtc *crtc,
+			     struct intel_crtc_state *crtc_state,
+			     struct dpll *reduced_clock)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	u32 dpll, fp, fp2;
+	int factor;
+
+	/* Enable autotuning of the PLL clock (if permissible) */
+	factor = 21;
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if ((intel_panel_use_ssc(dev_priv) &&
+		     dev_priv->vbt.lvds_ssc_freq == 100000) ||
+		    (HAS_PCH_IBX(dev_priv) &&
+		     intel_is_dual_link_lvds(dev_priv)))
+			factor = 25;
+	} else if (crtc_state->sdvo_tv_clock) {
+		factor = 20;
+	}
+
+	fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
+
+	if (ilk_needs_fb_cb_tune(&crtc_state->dpll, factor))
+		fp |= FP_CB_TUNE;
+
+	if (reduced_clock) {
+		fp2 = i9xx_dpll_compute_fp(reduced_clock);
+
+		if (reduced_clock->m < factor * reduced_clock->n)
+			fp2 |= FP_CB_TUNE;
+	} else {
+		fp2 = fp;
+	}
+
+	dpll = 0;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS))
+		dpll |= DPLLB_MODE_LVDS;
+	else
+		dpll |= DPLLB_MODE_DAC_SERIAL;
+
+	dpll |= (crtc_state->pixel_multiplier - 1)
+		<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO) ||
+	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+		dpll |= DPLL_SDVO_HIGH_SPEED;
+
+	if (intel_crtc_has_dp_encoder(crtc_state))
+		dpll |= DPLL_SDVO_HIGH_SPEED;
+
+	/*
+	 * The high speed IO clock is only really required for
+	 * SDVO/HDMI/DP, but we also enable it for CRT to make it
+	 * possible to share the DPLL between CRT and HDMI. Enabling
+	 * the clock needlessly does no real harm, except use up a
+	 * bit of power potentially.
+	 *
+	 * We'll limit this to IVB with 3 pipes, since it has only two
+	 * DPLLs and so DPLL sharing is the only way to get three pipes
+	 * driving PCH ports at the same time. On SNB we could do this,
+	 * and potentially avoid enabling the second DPLL, but it's not
+	 * clear if it''s a win or loss power wise. No point in doing
+	 * this on ILK at all since it has a fixed DPLL<->pipe mapping.
+	 */
+	if (INTEL_NUM_PIPES(dev_priv) == 3 &&
+	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG))
+		dpll |= DPLL_SDVO_HIGH_SPEED;
+
+	/* compute bitmask from p1 value */
+	dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+	/* also FPA1 */
+	dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
+
+	switch (crtc_state->dpll.p2) {
+	case 5:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+		break;
+	case 7:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+		break;
+	case 10:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+		break;
+	case 14:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+		break;
+	}
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+	    intel_panel_use_ssc(dev_priv))
+		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+	else
+		dpll |= PLL_REF_INPUT_DREFCLK;
+
+	dpll |= DPLL_VCO_ENABLE;
+
+	crtc_state->dpll_hw_state.dpll = dpll;
+	crtc_state->dpll_hw_state.fp0 = fp;
+	crtc_state->dpll_hw_state.fp1 = fp2;
+}
+
+static int ilk_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_atomic_state *state =
+		to_intel_atomic_state(crtc_state->uapi.state);
+	const struct intel_limit *limit;
+	int refclk = 120000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
+	if (!crtc_state->has_pch_encoder)
+		return 0;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "using SSC reference clock of %d kHz\n",
+				    dev_priv->vbt.lvds_ssc_freq);
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+		}
+
+		if (intel_is_dual_link_lvds(dev_priv)) {
+			if (refclk == 100000)
+				limit = &ilk_limits_dual_lvds_100m;
+			else
+				limit = &ilk_limits_dual_lvds;
+		} else {
+			if (refclk == 100000)
+				limit = &ilk_limits_single_lvds_100m;
+			else
+				limit = &ilk_limits_single_lvds;
+		}
+	} else {
+		limit = &ilk_limits_dac;
+	}
+
+	if (!crtc_state->clock_set &&
+	    !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		drm_err(&dev_priv->drm,
+			"Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	ilk_compute_dpll(crtc, crtc_state, NULL);
+
+	if (!intel_reserve_shared_dplls(state, crtc, NULL)) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "failed to find PLL for pipe %c\n",
+			    pipe_name(crtc->pipe));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void vlv_compute_dpll(struct intel_crtc *crtc,
+		      struct intel_crtc_state *pipe_config)
+{
+	pipe_config->dpll_hw_state.dpll = DPLL_INTEGRATED_REF_CLK_VLV |
+		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
+	if (crtc->pipe != PIPE_A)
+		pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
+	/* DPLL not used with DSI, but still need the rest set up */
+	if (!intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DSI))
+		pipe_config->dpll_hw_state.dpll |= DPLL_VCO_ENABLE |
+			DPLL_EXT_BUFFER_ENABLE_VLV;
+
+	pipe_config->dpll_hw_state.dpll_md =
+		(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+}
+
+void chv_compute_dpll(struct intel_crtc *crtc,
+		      struct intel_crtc_state *pipe_config)
+{
+	pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV |
+		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
+	if (crtc->pipe != PIPE_A)
+		pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
+	/* DPLL not used with DSI, but still need the rest set up */
+	if (!intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DSI))
+		pipe_config->dpll_hw_state.dpll |= DPLL_VCO_ENABLE;
+
+	pipe_config->dpll_hw_state.dpll_md =
+		(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+}
+
+static int chv_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	int refclk = 100000;
+	const struct intel_limit *limit = &intel_limits_chv;
+	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (!crtc_state->clock_set &&
+	    !chv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		drm_err(&i915->drm, "Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	chv_compute_dpll(crtc, crtc_state);
+
+	return 0;
+}
+
+static int vlv_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	int refclk = 100000;
+	const struct intel_limit *limit = &intel_limits_vlv;
+	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (!crtc_state->clock_set &&
+	    !vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		drm_err(&i915->drm,  "Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	vlv_compute_dpll(crtc, crtc_state);
+
+	return 0;
+}
+
+static int g4x_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	const struct intel_limit *limit;
+	int refclk = 96000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			drm_dbg_kms(&dev_priv->drm,
+				    "using SSC reference clock of %d kHz\n",
+				    refclk);
+		}
+
+		if (intel_is_dual_link_lvds(dev_priv))
+			limit = &intel_limits_g4x_dual_channel_lvds;
+		else
+			limit = &intel_limits_g4x_single_channel_lvds;
+	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) ||
+		   intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
+		limit = &intel_limits_g4x_hdmi;
+	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO)) {
+		limit = &intel_limits_g4x_sdvo;
+	} else {
+		/* The option is for other outputs */
+		limit = &intel_limits_i9xx_sdvo;
+	}
+
+	if (!crtc_state->clock_set &&
+	    !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		drm_err(&dev_priv->drm,
+			"Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+static int pnv_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	const struct intel_limit *limit;
+	int refclk = 96000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			drm_dbg_kms(&dev_priv->drm,
+				    "using SSC reference clock of %d kHz\n",
+				    refclk);
+		}
+
+		limit = &pnv_limits_lvds;
+	} else {
+		limit = &pnv_limits_sdvo;
+	}
+
+	if (!crtc_state->clock_set &&
+	    !pnv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		drm_err(&dev_priv->drm,
+			"Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
+				   struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	const struct intel_limit *limit;
+	int refclk = 96000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			drm_dbg_kms(&dev_priv->drm,
+				    "using SSC reference clock of %d kHz\n",
+				    refclk);
+		}
+
+		limit = &intel_limits_i9xx_lvds;
+	} else {
+		limit = &intel_limits_i9xx_sdvo;
+	}
+
+	if (!crtc_state->clock_set &&
+	    !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				 refclk, NULL, &crtc_state->dpll)) {
+		drm_err(&dev_priv->drm,
+			"Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+static int i8xx_crtc_compute_clock(struct intel_crtc *crtc,
+				   struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	const struct intel_limit *limit;
+	int refclk = 48000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			drm_dbg_kms(&dev_priv->drm,
+				    "using SSC reference clock of %d kHz\n",
+				    refclk);
+		}
+
+		limit = &intel_limits_i8xx_lvds;
+	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO)) {
+		limit = &intel_limits_i8xx_dvo;
+	} else {
+		limit = &intel_limits_i8xx_dac;
+	}
+
+	if (!crtc_state->clock_set &&
+	    !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				 refclk, NULL, &crtc_state->dpll)) {
+		drm_err(&dev_priv->drm,
+			"Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	i8xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+void
+intel_init_clock_hook(struct drm_i915_private *dev_priv)
+{
+	if (INTEL_GEN(dev_priv) >= 9 || HAS_DDI(dev_priv))
+		dev_priv->display.crtc_compute_clock = hsw_crtc_compute_clock;
+	else if (HAS_PCH_SPLIT(dev_priv))
+		dev_priv->display.crtc_compute_clock = ilk_crtc_compute_clock;
+	else if (IS_CHERRYVIEW(dev_priv))
+		dev_priv->display.crtc_compute_clock = chv_crtc_compute_clock;
+	else if (IS_VALLEYVIEW(dev_priv))
+		dev_priv->display.crtc_compute_clock = vlv_crtc_compute_clock;
+	else if (IS_G4X(dev_priv))
+		dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock;
+	else if (IS_PINEVIEW(dev_priv))
+		dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock;
+	else if (!IS_GEN(dev_priv, 2))
+		dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
+	else
+		dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock;
+}
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 7/9] drm/i915: split fdi code out from intel_display.c
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (5 preceding siblings ...)
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 6/9] drm/i915: refactor pll code out into intel_dpll_legacy.c Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 8/9] drm/i915: migrate hsw fdi code to new file Dave Airlie
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

This just refactors out the fdi code to a separate file.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  | 684 +-----------------
 drivers/gpu/drm/i915/display/intel_display.h  |  10 +
 .../drm/i915/display/intel_display_types.h    |   9 +
 drivers/gpu/drm/i915/display/intel_fdi.c      | 682 +++++++++++++++++
 5 files changed, 704 insertions(+), 682 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_fdi.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index accefd7b380e..d6003b676f0d 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -206,6 +206,7 @@ i915-y += \
 	display/intel_dpll_mgr.o \
 	display/intel_dsb.o \
 	display/intel_fbc.o \
+	display/intel_fdi.o \
 	display/intel_fifo_underrun.o \
 	display/intel_frontbuffer.o \
 	display/intel_global_state.o \
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index ff5b51dea661..b21ecc3c9289 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -170,16 +170,6 @@ static void intel_update_czclk(struct drm_i915_private *dev_priv)
 		dev_priv->czclk_freq);
 }
 
-/* units of 100MHz */
-static u32 intel_fdi_link_freq(struct drm_i915_private *dev_priv,
-			       const struct intel_crtc_state *pipe_config)
-{
-	if (HAS_DDI(dev_priv))
-		return pipe_config->port_clock; /* SPLL */
-	else
-		return dev_priv->fdi_pll_freq;
-}
-
 /* WA Display #0827: Gen9:all */
 static void
 skl_wa_827(struct drm_i915_private *dev_priv, enum pipe pipe, bool enable)
@@ -3764,532 +3754,6 @@ static void icl_set_pipe_chicken(struct intel_crtc *crtc)
 	intel_de_write(dev_priv, PIPE_CHICKEN(pipe), tmp);
 }
 
-static void intel_fdi_normal_train(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	enum pipe pipe = crtc->pipe;
-	i915_reg_t reg;
-	u32 temp;
-
-	/* enable normal train */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	if (IS_IVYBRIDGE(dev_priv)) {
-		temp &= ~FDI_LINK_TRAIN_NONE_IVB;
-		temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
-	} else {
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
-	}
-	intel_de_write(dev_priv, reg, temp);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	if (HAS_PCH_CPT(dev_priv)) {
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp |= FDI_LINK_TRAIN_NORMAL_CPT;
-	} else {
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_NONE;
-	}
-	intel_de_write(dev_priv, reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);
-
-	/* wait one idle pattern time */
-	intel_de_posting_read(dev_priv, reg);
-	udelay(1000);
-
-	/* IVB wants error correction enabled */
-	if (IS_IVYBRIDGE(dev_priv))
-		intel_de_write(dev_priv, reg,
-		               intel_de_read(dev_priv, reg) | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE);
-}
-
-/* The FDI link training functions for ILK/Ibexpeak. */
-static void ilk_fdi_link_train(struct intel_crtc *crtc,
-			       const struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	enum pipe pipe = crtc->pipe;
-	i915_reg_t reg;
-	u32 temp, tries;
-
-	/* FDI needs bits from pipe first */
-	assert_pipe_enabled(dev_priv, crtc_state->cpu_transcoder);
-
-	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
-	   for train result */
-	reg = FDI_RX_IMR(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_RX_SYMBOL_LOCK;
-	temp &= ~FDI_RX_BIT_LOCK;
-	intel_de_write(dev_priv, reg, temp);
-	intel_de_read(dev_priv, reg);
-	udelay(150);
-
-	/* enable CPU FDI TX and PCH FDI RX */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_DP_PORT_WIDTH_MASK;
-	temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_1;
-	intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_1;
-	intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(150);
-
-	/* Ironlake workaround, enable clock pointer after FDI enable*/
-	intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),
-		       FDI_RX_PHASE_SYNC_POINTER_OVR);
-	intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),
-		       FDI_RX_PHASE_SYNC_POINTER_OVR | FDI_RX_PHASE_SYNC_POINTER_EN);
-
-	reg = FDI_RX_IIR(pipe);
-	for (tries = 0; tries < 5; tries++) {
-		temp = intel_de_read(dev_priv, reg);
-		drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
-
-		if ((temp & FDI_RX_BIT_LOCK)) {
-			drm_dbg_kms(&dev_priv->drm, "FDI train 1 done.\n");
-			intel_de_write(dev_priv, reg, temp | FDI_RX_BIT_LOCK);
-			break;
-		}
-	}
-	if (tries == 5)
-		drm_err(&dev_priv->drm, "FDI train 1 fail!\n");
-
-	/* Train 2 */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_2;
-	intel_de_write(dev_priv, reg, temp);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_2;
-	intel_de_write(dev_priv, reg, temp);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(150);
-
-	reg = FDI_RX_IIR(pipe);
-	for (tries = 0; tries < 5; tries++) {
-		temp = intel_de_read(dev_priv, reg);
-		drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
-
-		if (temp & FDI_RX_SYMBOL_LOCK) {
-			intel_de_write(dev_priv, reg,
-				       temp | FDI_RX_SYMBOL_LOCK);
-			drm_dbg_kms(&dev_priv->drm, "FDI train 2 done.\n");
-			break;
-		}
-	}
-	if (tries == 5)
-		drm_err(&dev_priv->drm, "FDI train 2 fail!\n");
-
-	drm_dbg_kms(&dev_priv->drm, "FDI train done\n");
-
-}
-
-static const int snb_b_fdi_train_param[] = {
-	FDI_LINK_TRAIN_400MV_0DB_SNB_B,
-	FDI_LINK_TRAIN_400MV_6DB_SNB_B,
-	FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
-	FDI_LINK_TRAIN_800MV_0DB_SNB_B,
-};
-
-/* The FDI link training functions for SNB/Cougarpoint. */
-static void gen6_fdi_link_train(struct intel_crtc *crtc,
-				const struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	enum pipe pipe = crtc->pipe;
-	i915_reg_t reg;
-	u32 temp, i, retry;
-
-	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
-	   for train result */
-	reg = FDI_RX_IMR(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_RX_SYMBOL_LOCK;
-	temp &= ~FDI_RX_BIT_LOCK;
-	intel_de_write(dev_priv, reg, temp);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(150);
-
-	/* enable CPU FDI TX and PCH FDI RX */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_DP_PORT_WIDTH_MASK;
-	temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_1;
-	temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
-	/* SNB-B */
-	temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
-	intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);
-
-	intel_de_write(dev_priv, FDI_RX_MISC(pipe),
-		       FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	if (HAS_PCH_CPT(dev_priv)) {
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
-	} else {
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_PATTERN_1;
-	}
-	intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(150);
-
-	for (i = 0; i < 4; i++) {
-		reg = FDI_TX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
-		temp |= snb_b_fdi_train_param[i];
-		intel_de_write(dev_priv, reg, temp);
-
-		intel_de_posting_read(dev_priv, reg);
-		udelay(500);
-
-		for (retry = 0; retry < 5; retry++) {
-			reg = FDI_RX_IIR(pipe);
-			temp = intel_de_read(dev_priv, reg);
-			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
-			if (temp & FDI_RX_BIT_LOCK) {
-				intel_de_write(dev_priv, reg,
-					       temp | FDI_RX_BIT_LOCK);
-				drm_dbg_kms(&dev_priv->drm,
-					    "FDI train 1 done.\n");
-				break;
-			}
-			udelay(50);
-		}
-		if (retry < 5)
-			break;
-	}
-	if (i == 4)
-		drm_err(&dev_priv->drm, "FDI train 1 fail!\n");
-
-	/* Train 2 */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_2;
-	if (IS_GEN(dev_priv, 6)) {
-		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
-		/* SNB-B */
-		temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
-	}
-	intel_de_write(dev_priv, reg, temp);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	if (HAS_PCH_CPT(dev_priv)) {
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
-	} else {
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_PATTERN_2;
-	}
-	intel_de_write(dev_priv, reg, temp);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(150);
-
-	for (i = 0; i < 4; i++) {
-		reg = FDI_TX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
-		temp |= snb_b_fdi_train_param[i];
-		intel_de_write(dev_priv, reg, temp);
-
-		intel_de_posting_read(dev_priv, reg);
-		udelay(500);
-
-		for (retry = 0; retry < 5; retry++) {
-			reg = FDI_RX_IIR(pipe);
-			temp = intel_de_read(dev_priv, reg);
-			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
-			if (temp & FDI_RX_SYMBOL_LOCK) {
-				intel_de_write(dev_priv, reg,
-					       temp | FDI_RX_SYMBOL_LOCK);
-				drm_dbg_kms(&dev_priv->drm,
-					    "FDI train 2 done.\n");
-				break;
-			}
-			udelay(50);
-		}
-		if (retry < 5)
-			break;
-	}
-	if (i == 4)
-		drm_err(&dev_priv->drm, "FDI train 2 fail!\n");
-
-	drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");
-}
-
-/* Manual link training for Ivy Bridge A0 parts */
-static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,
-				      const struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	enum pipe pipe = crtc->pipe;
-	i915_reg_t reg;
-	u32 temp, i, j;
-
-	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
-	   for train result */
-	reg = FDI_RX_IMR(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_RX_SYMBOL_LOCK;
-	temp &= ~FDI_RX_BIT_LOCK;
-	intel_de_write(dev_priv, reg, temp);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(150);
-
-	drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR before link train 0x%x\n",
-		    intel_de_read(dev_priv, FDI_RX_IIR(pipe)));
-
-	/* Try each vswing and preemphasis setting twice before moving on */
-	for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) {
-		/* disable first in case we need to retry */
-		reg = FDI_TX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
-		temp &= ~FDI_TX_ENABLE;
-		intel_de_write(dev_priv, reg, temp);
-
-		reg = FDI_RX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp &= ~FDI_LINK_TRAIN_AUTO;
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp &= ~FDI_RX_ENABLE;
-		intel_de_write(dev_priv, reg, temp);
-
-		/* enable CPU FDI TX and PCH FDI RX */
-		reg = FDI_TX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp &= ~FDI_DP_PORT_WIDTH_MASK;
-		temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
-		temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
-		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
-		temp |= snb_b_fdi_train_param[j/2];
-		temp |= FDI_COMPOSITE_SYNC;
-		intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);
-
-		intel_de_write(dev_priv, FDI_RX_MISC(pipe),
-			       FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
-
-		reg = FDI_RX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
-		temp |= FDI_COMPOSITE_SYNC;
-		intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);
-
-		intel_de_posting_read(dev_priv, reg);
-		udelay(1); /* should be 0.5us */
-
-		for (i = 0; i < 4; i++) {
-			reg = FDI_RX_IIR(pipe);
-			temp = intel_de_read(dev_priv, reg);
-			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
-
-			if (temp & FDI_RX_BIT_LOCK ||
-			    (intel_de_read(dev_priv, reg) & FDI_RX_BIT_LOCK)) {
-				intel_de_write(dev_priv, reg,
-					       temp | FDI_RX_BIT_LOCK);
-				drm_dbg_kms(&dev_priv->drm,
-					    "FDI train 1 done, level %i.\n",
-					    i);
-				break;
-			}
-			udelay(1); /* should be 0.5us */
-		}
-		if (i == 4) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "FDI train 1 fail on vswing %d\n", j / 2);
-			continue;
-		}
-
-		/* Train 2 */
-		reg = FDI_TX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp &= ~FDI_LINK_TRAIN_NONE_IVB;
-		temp |= FDI_LINK_TRAIN_PATTERN_2_IVB;
-		intel_de_write(dev_priv, reg, temp);
-
-		reg = FDI_RX_CTL(pipe);
-		temp = intel_de_read(dev_priv, reg);
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
-		intel_de_write(dev_priv, reg, temp);
-
-		intel_de_posting_read(dev_priv, reg);
-		udelay(2); /* should be 1.5us */
-
-		for (i = 0; i < 4; i++) {
-			reg = FDI_RX_IIR(pipe);
-			temp = intel_de_read(dev_priv, reg);
-			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
-
-			if (temp & FDI_RX_SYMBOL_LOCK ||
-			    (intel_de_read(dev_priv, reg) & FDI_RX_SYMBOL_LOCK)) {
-				intel_de_write(dev_priv, reg,
-					       temp | FDI_RX_SYMBOL_LOCK);
-				drm_dbg_kms(&dev_priv->drm,
-					    "FDI train 2 done, level %i.\n",
-					    i);
-				goto train_done;
-			}
-			udelay(2); /* should be 1.5us */
-		}
-		if (i == 4)
-			drm_dbg_kms(&dev_priv->drm,
-				    "FDI train 2 fail on vswing %d\n", j / 2);
-	}
-
-train_done:
-	drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");
-}
-
-static void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
-	enum pipe pipe = intel_crtc->pipe;
-	i915_reg_t reg;
-	u32 temp;
-
-	/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16));
-	temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
-	temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
-	intel_de_write(dev_priv, reg, temp | FDI_RX_PLL_ENABLE);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(200);
-
-	/* Switch from Rawclk to PCDclk */
-	temp = intel_de_read(dev_priv, reg);
-	intel_de_write(dev_priv, reg, temp | FDI_PCDCLK);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(200);
-
-	/* Enable CPU FDI TX PLL, always on for Ironlake */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	if ((temp & FDI_TX_PLL_ENABLE) == 0) {
-		intel_de_write(dev_priv, reg, temp | FDI_TX_PLL_ENABLE);
-
-		intel_de_posting_read(dev_priv, reg);
-		udelay(100);
-	}
-}
-
-static void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc)
-{
-	struct drm_device *dev = intel_crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	enum pipe pipe = intel_crtc->pipe;
-	i915_reg_t reg;
-	u32 temp;
-
-	/* Switch from PCDclk to Rawclk */
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	intel_de_write(dev_priv, reg, temp & ~FDI_PCDCLK);
-
-	/* Disable CPU FDI TX PLL */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	intel_de_write(dev_priv, reg, temp & ~FDI_TX_PLL_ENABLE);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(100);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	intel_de_write(dev_priv, reg, temp & ~FDI_RX_PLL_ENABLE);
-
-	/* Wait for the clocks to turn off. */
-	intel_de_posting_read(dev_priv, reg);
-	udelay(100);
-}
-
-static void ilk_fdi_disable(struct intel_crtc *crtc)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	enum pipe pipe = crtc->pipe;
-	i915_reg_t reg;
-	u32 temp;
-
-	/* disable CPU FDI tx and PCH FDI rx */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	intel_de_write(dev_priv, reg, temp & ~FDI_TX_ENABLE);
-	intel_de_posting_read(dev_priv, reg);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~(0x7 << 16);
-	temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
-	intel_de_write(dev_priv, reg, temp & ~FDI_RX_ENABLE);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(100);
-
-	/* Ironlake workaround, disable clock pointer after downing FDI */
-	if (HAS_PCH_IBX(dev_priv))
-		intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),
-			       FDI_RX_PHASE_SYNC_POINTER_OVR);
-
-	/* still set train pattern 1 */
-	reg = FDI_TX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_1;
-	intel_de_write(dev_priv, reg, temp);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = intel_de_read(dev_priv, reg);
-	if (HAS_PCH_CPT(dev_priv)) {
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
-	} else {
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_PATTERN_1;
-	}
-	/* BPC in FDI rx is consistent with that in PIPECONF */
-	temp &= ~(0x07 << 16);
-	temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
-	intel_de_write(dev_priv, reg, temp);
-
-	intel_de_posting_read(dev_priv, reg);
-	udelay(100);
-}
-
 bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv)
 {
 	struct drm_crtc *crtc;
@@ -6696,143 +6160,6 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
 	}
 }
 
-static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
-{
-	if (crtc_state->hw.enable && crtc_state->has_pch_encoder)
-		return crtc_state->fdi_lanes;
-
-	return 0;
-}
-
-static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
-			       struct intel_crtc_state *pipe_config)
-{
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_atomic_state *state = pipe_config->uapi.state;
-	struct intel_crtc *other_crtc;
-	struct intel_crtc_state *other_crtc_state;
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "checking fdi config on pipe %c, lanes %i\n",
-		    pipe_name(pipe), pipe_config->fdi_lanes);
-	if (pipe_config->fdi_lanes > 4) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "invalid fdi lane config on pipe %c: %i lanes\n",
-			    pipe_name(pipe), pipe_config->fdi_lanes);
-		return -EINVAL;
-	}
-
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
-		if (pipe_config->fdi_lanes > 2) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "only 2 lanes on haswell, required: %i lanes\n",
-				    pipe_config->fdi_lanes);
-			return -EINVAL;
-		} else {
-			return 0;
-		}
-	}
-
-	if (INTEL_NUM_PIPES(dev_priv) == 2)
-		return 0;
-
-	/* Ivybridge 3 pipe is really complicated */
-	switch (pipe) {
-	case PIPE_A:
-		return 0;
-	case PIPE_B:
-		if (pipe_config->fdi_lanes <= 2)
-			return 0;
-
-		other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_C);
-		other_crtc_state =
-			intel_atomic_get_crtc_state(state, other_crtc);
-		if (IS_ERR(other_crtc_state))
-			return PTR_ERR(other_crtc_state);
-
-		if (pipe_required_fdi_lanes(other_crtc_state) > 0) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "invalid shared fdi lane config on pipe %c: %i lanes\n",
-				    pipe_name(pipe), pipe_config->fdi_lanes);
-			return -EINVAL;
-		}
-		return 0;
-	case PIPE_C:
-		if (pipe_config->fdi_lanes > 2) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "only 2 lanes on pipe %c: required %i lanes\n",
-				    pipe_name(pipe), pipe_config->fdi_lanes);
-			return -EINVAL;
-		}
-
-		other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_B);
-		other_crtc_state =
-			intel_atomic_get_crtc_state(state, other_crtc);
-		if (IS_ERR(other_crtc_state))
-			return PTR_ERR(other_crtc_state);
-
-		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "fdi link B uses too many lanes to enable link C\n");
-			return -EINVAL;
-		}
-		return 0;
-	default:
-		BUG();
-	}
-}
-
-#define RETRY 1
-static int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
-				  struct intel_crtc_state *pipe_config)
-{
-	struct drm_device *dev = intel_crtc->base.dev;
-	struct drm_i915_private *i915 = to_i915(dev);
-	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
-	int lane, link_bw, fdi_dotclock, ret;
-	bool needs_recompute = false;
-
-retry:
-	/* FDI is a binary signal running at ~2.7GHz, encoding
-	 * each output octet as 10 bits. The actual frequency
-	 * is stored as a divider into a 100MHz clock, and the
-	 * mode pixel clock is stored in units of 1KHz.
-	 * Hence the bw of each lane in terms of the mode signal
-	 * is:
-	 */
-	link_bw = intel_fdi_link_freq(i915, pipe_config);
-
-	fdi_dotclock = adjusted_mode->crtc_clock;
-
-	lane = ilk_get_lanes_required(fdi_dotclock, link_bw,
-				      pipe_config->pipe_bpp);
-
-	pipe_config->fdi_lanes = lane;
-
-	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
-			       link_bw, &pipe_config->fdi_m_n, false, false);
-
-	ret = ilk_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);
-	if (ret == -EDEADLK)
-		return ret;
-
-	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
-		pipe_config->pipe_bpp -= 2*3;
-		drm_dbg_kms(&i915->drm,
-			    "fdi link bw constraint, reducing pipe bpp to %i\n",
-			    pipe_config->pipe_bpp);
-		needs_recompute = true;
-		pipe_config->bw_constrained = true;
-
-		goto retry;
-	}
-
-	if (needs_recompute)
-		return RETRY;
-
-	return ret;
-}
-
 bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -11367,7 +10694,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 		return ret;
 	}
 
-	if (ret == RETRY) {
+	if (ret == I915_DISPLAY_CONFIG_RETRY) {
 		if (drm_WARN(&i915->drm, !retry,
 			     "loop in pipe configuration computation\n"))
 			return -EINVAL;
@@ -15166,14 +14493,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 	}
 
-	if (IS_GEN(dev_priv, 5)) {
-		dev_priv->display.fdi_link_train = ilk_fdi_link_train;
-	} else if (IS_GEN(dev_priv, 6)) {
-		dev_priv->display.fdi_link_train = gen6_fdi_link_train;
-	} else if (IS_IVYBRIDGE(dev_priv)) {
-		/* FIXME: detect B0+ stepping and use auto training */
-		dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
-	}
+	intel_init_fdi_hook(dev_priv);
 
 	if (INTEL_GEN(dev_priv) >= 9) {
 		dev_priv->display.commit_modeset_enables = skl_commit_modeset_enables;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index f1e36cca86c1..731ea6f7777a 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -677,6 +677,16 @@ void vlv_compute_dpll(struct intel_crtc *crtc,
 void chv_compute_dpll(struct intel_crtc *crtc,
 		      struct intel_crtc_state *pipe_config);
 
+/* fdi */
+#define I915_DISPLAY_CONFIG_RETRY 1
+int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
+			   struct intel_crtc_state *pipe_config);
+void intel_fdi_normal_train(struct intel_crtc *crtc);
+void ilk_fdi_disable(struct intel_crtc *crtc);
+void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
+void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state);
+void intel_init_fdi_hook(struct drm_i915_private *dev_priv);
+
 /* modesetting */
 void intel_modeset_init_hw(struct drm_i915_private *i915);
 int intel_modeset_init_noirq(struct drm_i915_private *i915);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 5d015b0710f2..6d2782069855 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1816,4 +1816,13 @@ static inline u32 i9xx_dpll_compute_fp(struct dpll *dpll)
 	return dpll->n << 16 | dpll->m1 << 8 | dpll->m2;
 }
 
+static inline u32 intel_fdi_link_freq(struct drm_i915_private *dev_priv,
+				      const struct intel_crtc_state *pipe_config)
+{
+	if (HAS_DDI(dev_priv))
+		return pipe_config->port_clock; /* SPLL */
+	else
+		return dev_priv->fdi_pll_freq;
+}
+
 #endif /*  __INTEL_DISPLAY_TYPES_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
new file mode 100644
index 000000000000..bf4ef84686ef
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -0,0 +1,682 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#include "intel_atomic.h"
+#include "intel_display_types.h"
+
+/* units of 100MHz */
+static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
+{
+	if (crtc_state->hw.enable && crtc_state->has_pch_encoder)
+		return crtc_state->fdi_lanes;
+
+	return 0;
+}
+
+static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
+			       struct intel_crtc_state *pipe_config)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_atomic_state *state = pipe_config->uapi.state;
+	struct intel_crtc *other_crtc;
+	struct intel_crtc_state *other_crtc_state;
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "checking fdi config on pipe %c, lanes %i\n",
+		    pipe_name(pipe), pipe_config->fdi_lanes);
+	if (pipe_config->fdi_lanes > 4) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "invalid fdi lane config on pipe %c: %i lanes\n",
+			    pipe_name(pipe), pipe_config->fdi_lanes);
+		return -EINVAL;
+	}
+
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
+		if (pipe_config->fdi_lanes > 2) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "only 2 lanes on haswell, required: %i lanes\n",
+				    pipe_config->fdi_lanes);
+			return -EINVAL;
+		} else {
+			return 0;
+		}
+	}
+
+	if (INTEL_NUM_PIPES(dev_priv) == 2)
+		return 0;
+
+	/* Ivybridge 3 pipe is really complicated */
+	switch (pipe) {
+	case PIPE_A:
+		return 0;
+	case PIPE_B:
+		if (pipe_config->fdi_lanes <= 2)
+			return 0;
+
+		other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_C);
+		other_crtc_state =
+			intel_atomic_get_crtc_state(state, other_crtc);
+		if (IS_ERR(other_crtc_state))
+			return PTR_ERR(other_crtc_state);
+
+		if (pipe_required_fdi_lanes(other_crtc_state) > 0) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "invalid shared fdi lane config on pipe %c: %i lanes\n",
+				    pipe_name(pipe), pipe_config->fdi_lanes);
+			return -EINVAL;
+		}
+		return 0;
+	case PIPE_C:
+		if (pipe_config->fdi_lanes > 2) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "only 2 lanes on pipe %c: required %i lanes\n",
+				    pipe_name(pipe), pipe_config->fdi_lanes);
+			return -EINVAL;
+		}
+
+		other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_B);
+		other_crtc_state =
+			intel_atomic_get_crtc_state(state, other_crtc);
+		if (IS_ERR(other_crtc_state))
+			return PTR_ERR(other_crtc_state);
+
+		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "fdi link B uses too many lanes to enable link C\n");
+			return -EINVAL;
+		}
+		return 0;
+	default:
+		BUG();
+	}
+}
+
+int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
+				  struct intel_crtc_state *pipe_config)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *i915 = to_i915(dev);
+	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
+	int lane, link_bw, fdi_dotclock, ret;
+	bool needs_recompute = false;
+
+retry:
+	/* FDI is a binary signal running at ~2.7GHz, encoding
+	 * each output octet as 10 bits. The actual frequency
+	 * is stored as a divider into a 100MHz clock, and the
+	 * mode pixel clock is stored in units of 1KHz.
+	 * Hence the bw of each lane in terms of the mode signal
+	 * is:
+	 */
+	link_bw = intel_fdi_link_freq(i915, pipe_config);
+
+	fdi_dotclock = adjusted_mode->crtc_clock;
+
+	lane = ilk_get_lanes_required(fdi_dotclock, link_bw,
+				      pipe_config->pipe_bpp);
+
+	pipe_config->fdi_lanes = lane;
+
+	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
+			       link_bw, &pipe_config->fdi_m_n, false, false);
+
+	ret = ilk_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);
+	if (ret == -EDEADLK)
+		return ret;
+
+	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
+		pipe_config->pipe_bpp -= 2*3;
+		drm_dbg_kms(&i915->drm,
+			    "fdi link bw constraint, reducing pipe bpp to %i\n",
+			    pipe_config->pipe_bpp);
+		needs_recompute = true;
+		pipe_config->bw_constrained = true;
+
+		goto retry;
+	}
+
+	if (needs_recompute)
+		return I915_DISPLAY_CONFIG_RETRY;
+
+	return ret;
+}
+
+void intel_fdi_normal_train(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	enum pipe pipe = crtc->pipe;
+	i915_reg_t reg;
+	u32 temp;
+
+	/* enable normal train */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	if (IS_IVYBRIDGE(dev_priv)) {
+		temp &= ~FDI_LINK_TRAIN_NONE_IVB;
+		temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
+	} else {
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
+	}
+	intel_de_write(dev_priv, reg, temp);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	if (HAS_PCH_CPT(dev_priv)) {
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp |= FDI_LINK_TRAIN_NORMAL_CPT;
+	} else {
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_NONE;
+	}
+	intel_de_write(dev_priv, reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);
+
+	/* wait one idle pattern time */
+	intel_de_posting_read(dev_priv, reg);
+	udelay(1000);
+
+	/* IVB wants error correction enabled */
+	if (IS_IVYBRIDGE(dev_priv))
+		intel_de_write(dev_priv, reg,
+			       intel_de_read(dev_priv, reg) | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE);
+}
+
+/* The FDI link training functions for ILK/Ibexpeak. */
+static void ilk_fdi_link_train(struct intel_crtc *crtc,
+			       const struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	enum pipe pipe = crtc->pipe;
+	i915_reg_t reg;
+	u32 temp, tries;
+
+	/* FDI needs bits from pipe first */
+	assert_pipe_enabled(dev_priv, crtc_state->cpu_transcoder);
+
+	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+	   for train result */
+	reg = FDI_RX_IMR(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_RX_SYMBOL_LOCK;
+	temp &= ~FDI_RX_BIT_LOCK;
+	intel_de_write(dev_priv, reg, temp);
+	intel_de_read(dev_priv, reg);
+	udelay(150);
+
+	/* enable CPU FDI TX and PCH FDI RX */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_DP_PORT_WIDTH_MASK;
+	temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_1;
+	intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_1;
+	intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(150);
+
+	/* Ironlake workaround, enable clock pointer after FDI enable*/
+	intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),
+		       FDI_RX_PHASE_SYNC_POINTER_OVR);
+	intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),
+		       FDI_RX_PHASE_SYNC_POINTER_OVR | FDI_RX_PHASE_SYNC_POINTER_EN);
+
+	reg = FDI_RX_IIR(pipe);
+	for (tries = 0; tries < 5; tries++) {
+		temp = intel_de_read(dev_priv, reg);
+		drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
+
+		if ((temp & FDI_RX_BIT_LOCK)) {
+			drm_dbg_kms(&dev_priv->drm, "FDI train 1 done.\n");
+			intel_de_write(dev_priv, reg, temp | FDI_RX_BIT_LOCK);
+			break;
+		}
+	}
+	if (tries == 5)
+		drm_err(&dev_priv->drm, "FDI train 1 fail!\n");
+
+	/* Train 2 */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_2;
+	intel_de_write(dev_priv, reg, temp);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_2;
+	intel_de_write(dev_priv, reg, temp);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(150);
+
+	reg = FDI_RX_IIR(pipe);
+	for (tries = 0; tries < 5; tries++) {
+		temp = intel_de_read(dev_priv, reg);
+		drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
+
+		if (temp & FDI_RX_SYMBOL_LOCK) {
+			intel_de_write(dev_priv, reg,
+				       temp | FDI_RX_SYMBOL_LOCK);
+			drm_dbg_kms(&dev_priv->drm, "FDI train 2 done.\n");
+			break;
+		}
+	}
+	if (tries == 5)
+		drm_err(&dev_priv->drm, "FDI train 2 fail!\n");
+
+	drm_dbg_kms(&dev_priv->drm, "FDI train done\n");
+
+}
+
+static const int snb_b_fdi_train_param[] = {
+	FDI_LINK_TRAIN_400MV_0DB_SNB_B,
+	FDI_LINK_TRAIN_400MV_6DB_SNB_B,
+	FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
+	FDI_LINK_TRAIN_800MV_0DB_SNB_B,
+};
+
+/* The FDI link training functions for SNB/Cougarpoint. */
+static void gen6_fdi_link_train(struct intel_crtc *crtc,
+				const struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	enum pipe pipe = crtc->pipe;
+	i915_reg_t reg;
+	u32 temp, i, retry;
+
+	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+	   for train result */
+	reg = FDI_RX_IMR(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_RX_SYMBOL_LOCK;
+	temp &= ~FDI_RX_BIT_LOCK;
+	intel_de_write(dev_priv, reg, temp);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(150);
+
+	/* enable CPU FDI TX and PCH FDI RX */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_DP_PORT_WIDTH_MASK;
+	temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_1;
+	temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+	/* SNB-B */
+	temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+	intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);
+
+	intel_de_write(dev_priv, FDI_RX_MISC(pipe),
+		       FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	if (HAS_PCH_CPT(dev_priv)) {
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+	} else {
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_1;
+	}
+	intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(150);
+
+	for (i = 0; i < 4; i++) {
+		reg = FDI_TX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+		temp |= snb_b_fdi_train_param[i];
+		intel_de_write(dev_priv, reg, temp);
+
+		intel_de_posting_read(dev_priv, reg);
+		udelay(500);
+
+		for (retry = 0; retry < 5; retry++) {
+			reg = FDI_RX_IIR(pipe);
+			temp = intel_de_read(dev_priv, reg);
+			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
+			if (temp & FDI_RX_BIT_LOCK) {
+				intel_de_write(dev_priv, reg,
+					       temp | FDI_RX_BIT_LOCK);
+				drm_dbg_kms(&dev_priv->drm,
+					    "FDI train 1 done.\n");
+				break;
+			}
+			udelay(50);
+		}
+		if (retry < 5)
+			break;
+	}
+	if (i == 4)
+		drm_err(&dev_priv->drm, "FDI train 1 fail!\n");
+
+	/* Train 2 */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_2;
+	if (IS_GEN(dev_priv, 6)) {
+		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+		/* SNB-B */
+		temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+	}
+	intel_de_write(dev_priv, reg, temp);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	if (HAS_PCH_CPT(dev_priv)) {
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
+	} else {
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_2;
+	}
+	intel_de_write(dev_priv, reg, temp);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(150);
+
+	for (i = 0; i < 4; i++) {
+		reg = FDI_TX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+		temp |= snb_b_fdi_train_param[i];
+		intel_de_write(dev_priv, reg, temp);
+
+		intel_de_posting_read(dev_priv, reg);
+		udelay(500);
+
+		for (retry = 0; retry < 5; retry++) {
+			reg = FDI_RX_IIR(pipe);
+			temp = intel_de_read(dev_priv, reg);
+			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
+			if (temp & FDI_RX_SYMBOL_LOCK) {
+				intel_de_write(dev_priv, reg,
+					       temp | FDI_RX_SYMBOL_LOCK);
+				drm_dbg_kms(&dev_priv->drm,
+					    "FDI train 2 done.\n");
+				break;
+			}
+			udelay(50);
+		}
+		if (retry < 5)
+			break;
+	}
+	if (i == 4)
+		drm_err(&dev_priv->drm, "FDI train 2 fail!\n");
+
+	drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");
+}
+
+/* Manual link training for Ivy Bridge A0 parts */
+static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,
+				      const struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	enum pipe pipe = crtc->pipe;
+	i915_reg_t reg;
+	u32 temp, i, j;
+
+	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+	   for train result */
+	reg = FDI_RX_IMR(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_RX_SYMBOL_LOCK;
+	temp &= ~FDI_RX_BIT_LOCK;
+	intel_de_write(dev_priv, reg, temp);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(150);
+
+	drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR before link train 0x%x\n",
+		    intel_de_read(dev_priv, FDI_RX_IIR(pipe)));
+
+	/* Try each vswing and preemphasis setting twice before moving on */
+	for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) {
+		/* disable first in case we need to retry */
+		reg = FDI_TX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
+		temp &= ~FDI_TX_ENABLE;
+		intel_de_write(dev_priv, reg, temp);
+
+		reg = FDI_RX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp &= ~FDI_LINK_TRAIN_AUTO;
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp &= ~FDI_RX_ENABLE;
+		intel_de_write(dev_priv, reg, temp);
+
+		/* enable CPU FDI TX and PCH FDI RX */
+		reg = FDI_TX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp &= ~FDI_DP_PORT_WIDTH_MASK;
+		temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
+		temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
+		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+		temp |= snb_b_fdi_train_param[j/2];
+		temp |= FDI_COMPOSITE_SYNC;
+		intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);
+
+		intel_de_write(dev_priv, FDI_RX_MISC(pipe),
+			       FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+
+		reg = FDI_RX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+		temp |= FDI_COMPOSITE_SYNC;
+		intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);
+
+		intel_de_posting_read(dev_priv, reg);
+		udelay(1); /* should be 0.5us */
+
+		for (i = 0; i < 4; i++) {
+			reg = FDI_RX_IIR(pipe);
+			temp = intel_de_read(dev_priv, reg);
+			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
+
+			if (temp & FDI_RX_BIT_LOCK ||
+			    (intel_de_read(dev_priv, reg) & FDI_RX_BIT_LOCK)) {
+				intel_de_write(dev_priv, reg,
+					       temp | FDI_RX_BIT_LOCK);
+				drm_dbg_kms(&dev_priv->drm,
+					    "FDI train 1 done, level %i.\n",
+					    i);
+				break;
+			}
+			udelay(1); /* should be 0.5us */
+		}
+		if (i == 4) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "FDI train 1 fail on vswing %d\n", j / 2);
+			continue;
+		}
+
+		/* Train 2 */
+		reg = FDI_TX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp &= ~FDI_LINK_TRAIN_NONE_IVB;
+		temp |= FDI_LINK_TRAIN_PATTERN_2_IVB;
+		intel_de_write(dev_priv, reg, temp);
+
+		reg = FDI_RX_CTL(pipe);
+		temp = intel_de_read(dev_priv, reg);
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
+		intel_de_write(dev_priv, reg, temp);
+
+		intel_de_posting_read(dev_priv, reg);
+		udelay(2); /* should be 1.5us */
+
+		for (i = 0; i < 4; i++) {
+			reg = FDI_RX_IIR(pipe);
+			temp = intel_de_read(dev_priv, reg);
+			drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);
+
+			if (temp & FDI_RX_SYMBOL_LOCK ||
+			    (intel_de_read(dev_priv, reg) & FDI_RX_SYMBOL_LOCK)) {
+				intel_de_write(dev_priv, reg,
+					       temp | FDI_RX_SYMBOL_LOCK);
+				drm_dbg_kms(&dev_priv->drm,
+					    "FDI train 2 done, level %i.\n",
+					    i);
+				goto train_done;
+			}
+			udelay(2); /* should be 1.5us */
+		}
+		if (i == 4)
+			drm_dbg_kms(&dev_priv->drm,
+				    "FDI train 2 fail on vswing %d\n", j / 2);
+	}
+
+train_done:
+	drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");
+}
+
+void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	enum pipe pipe = intel_crtc->pipe;
+	i915_reg_t reg;
+	u32 temp;
+
+	/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16));
+	temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
+	temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
+	intel_de_write(dev_priv, reg, temp | FDI_RX_PLL_ENABLE);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(200);
+
+	/* Switch from Rawclk to PCDclk */
+	temp = intel_de_read(dev_priv, reg);
+	intel_de_write(dev_priv, reg, temp | FDI_PCDCLK);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(200);
+
+	/* Enable CPU FDI TX PLL, always on for Ironlake */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	if ((temp & FDI_TX_PLL_ENABLE) == 0) {
+		intel_de_write(dev_priv, reg, temp | FDI_TX_PLL_ENABLE);
+
+		intel_de_posting_read(dev_priv, reg);
+		udelay(100);
+	}
+}
+
+void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	enum pipe pipe = intel_crtc->pipe;
+	i915_reg_t reg;
+	u32 temp;
+
+	/* Switch from PCDclk to Rawclk */
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	intel_de_write(dev_priv, reg, temp & ~FDI_PCDCLK);
+
+	/* Disable CPU FDI TX PLL */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	intel_de_write(dev_priv, reg, temp & ~FDI_TX_PLL_ENABLE);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(100);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	intel_de_write(dev_priv, reg, temp & ~FDI_RX_PLL_ENABLE);
+
+	/* Wait for the clocks to turn off. */
+	intel_de_posting_read(dev_priv, reg);
+	udelay(100);
+}
+
+void ilk_fdi_disable(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
+	i915_reg_t reg;
+	u32 temp;
+
+	/* disable CPU FDI tx and PCH FDI rx */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	intel_de_write(dev_priv, reg, temp & ~FDI_TX_ENABLE);
+	intel_de_posting_read(dev_priv, reg);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~(0x7 << 16);
+	temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
+	intel_de_write(dev_priv, reg, temp & ~FDI_RX_ENABLE);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(100);
+
+	/* Ironlake workaround, disable clock pointer after downing FDI */
+	if (HAS_PCH_IBX(dev_priv))
+		intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),
+			       FDI_RX_PHASE_SYNC_POINTER_OVR);
+
+	/* still set train pattern 1 */
+	reg = FDI_TX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_1;
+	intel_de_write(dev_priv, reg, temp);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = intel_de_read(dev_priv, reg);
+	if (HAS_PCH_CPT(dev_priv)) {
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+	} else {
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_1;
+	}
+	/* BPC in FDI rx is consistent with that in PIPECONF */
+	temp &= ~(0x07 << 16);
+	temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
+	intel_de_write(dev_priv, reg, temp);
+
+	intel_de_posting_read(dev_priv, reg);
+	udelay(100);
+}
+
+void
+intel_init_fdi_hook(struct drm_i915_private *dev_priv)
+{
+	if (IS_GEN(dev_priv, 5)) {
+		dev_priv->display.fdi_link_train = ilk_fdi_link_train;
+	} else if (IS_GEN(dev_priv, 6)) {
+		dev_priv->display.fdi_link_train = gen6_fdi_link_train;
+	} else if (IS_IVYBRIDGE(dev_priv)) {
+		/* FIXME: detect B0+ stepping and use auto training */
+		dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
+	}
+}
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 8/9] drm/i915: migrate hsw fdi code to new file.
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (6 preceding siblings ...)
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 7/9] drm/i915: split fdi code out from intel_display.c Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 9/9] drm/i915: migrate skl planes code " Dave Airlie
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

Daniel asked for this, but it's a bit messy and I'm not sure
how best to clean it up yet.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c     | 151 +------------------
 drivers/gpu/drm/i915/display/intel_ddi.h     |  14 +-
 drivers/gpu/drm/i915/display/intel_display.h |   2 +
 drivers/gpu/drm/i915/display/intel_fdi.c     | 147 ++++++++++++++++++
 4 files changed, 166 insertions(+), 148 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 6863236df1d0..2d903962f9dd 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -51,12 +51,6 @@
 #include "intel_tc.h"
 #include "intel_vdsc.h"
 
-struct ddi_buf_trans {
-	u32 trans1;	/* balance leg enable, de-emph level */
-	u32 trans2;	/* vref sel, vswing */
-	u8 i_boost;	/* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */
-};
-
 static const u8 index_to_dp_signal_levels[] = {
 	[0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0,
 	[1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1,
@@ -1398,8 +1392,8 @@ static int intel_ddi_hdmi_level(struct intel_encoder *encoder,
  * values in advance. This function programs the correct values for
  * DP/eDP/FDI use cases.
  */
-static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
-					 const struct intel_crtc_state *crtc_state)
+void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
+				  const struct intel_crtc_state *crtc_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	u32 iboost_bit = 0;
@@ -1461,8 +1455,8 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
 		       ddi_translations[level].trans2);
 }
 
-static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
-				    enum port port)
+void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
+			     enum port port)
 {
 	if (IS_BROXTON(dev_priv)) {
 		udelay(16);
@@ -1490,7 +1484,7 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
 			port_name(port));
 }
 
-static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
+u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
 {
 	switch (pll->info->id) {
 	case DPLL_ID_WRPLL1:
@@ -1550,141 +1544,6 @@ static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
 	}
 }
 
-/* Starting with Haswell, different DDI ports can work in FDI mode for
- * connection to the PCH-located connectors. For this, it is necessary to train
- * both the DDI port and PCH receiver for the desired DDI buffer settings.
- *
- * The recommended port to work in FDI mode is DDI E, which we use here. Also,
- * please note that when FDI mode is active on DDI E, it shares 2 lines with
- * DDI A (which is used for eDP)
- */
-
-void hsw_fdi_link_train(struct intel_encoder *encoder,
-			const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	u32 temp, i, rx_ctl_val, ddi_pll_sel;
-
-	intel_prepare_dp_ddi_buffers(encoder, crtc_state);
-
-	/* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
-	 * mode set "sequence for CRT port" document:
-	 * - TP1 to TP2 time with the default value
-	 * - FDI delay to 90h
-	 *
-	 * WaFDIAutoLinkSetTimingOverrride:hsw
-	 */
-	intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A),
-		       FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2) | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
-
-	/* Enable the PCH Receiver FDI PLL */
-	rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
-		     FDI_RX_PLL_ENABLE |
-		     FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
-	intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
-	intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
-	udelay(220);
-
-	/* Switch from Rawclk to PCDclk */
-	rx_ctl_val |= FDI_PCDCLK;
-	intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
-
-	/* Configure Port Clock Select */
-	ddi_pll_sel = hsw_pll_to_ddi_pll_sel(crtc_state->shared_dpll);
-	intel_de_write(dev_priv, PORT_CLK_SEL(PORT_E), ddi_pll_sel);
-	drm_WARN_ON(&dev_priv->drm, ddi_pll_sel != PORT_CLK_SEL_SPLL);
-
-	/* Start the training iterating through available voltages and emphasis,
-	 * testing each value twice. */
-	for (i = 0; i < ARRAY_SIZE(hsw_ddi_translations_fdi) * 2; i++) {
-		/* Configure DP_TP_CTL with auto-training */
-		intel_de_write(dev_priv, DP_TP_CTL(PORT_E),
-			       DP_TP_CTL_FDI_AUTOTRAIN |
-			       DP_TP_CTL_ENHANCED_FRAME_ENABLE |
-			       DP_TP_CTL_LINK_TRAIN_PAT1 |
-			       DP_TP_CTL_ENABLE);
-
-		/* Configure and enable DDI_BUF_CTL for DDI E with next voltage.
-		 * DDI E does not support port reversal, the functionality is
-		 * achieved on the PCH side in FDI_RX_CTL, so no need to set the
-		 * port reversal bit */
-		intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E),
-			       DDI_BUF_CTL_ENABLE | ((crtc_state->fdi_lanes - 1) << 1) | DDI_BUF_TRANS_SELECT(i / 2));
-		intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
-
-		udelay(600);
-
-		/* Program PCH FDI Receiver TU */
-		intel_de_write(dev_priv, FDI_RX_TUSIZE1(PIPE_A), TU_SIZE(64));
-
-		/* Enable PCH FDI Receiver with auto-training */
-		rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO;
-		intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
-		intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
-
-		/* Wait for FDI receiver lane calibration */
-		udelay(30);
-
-		/* Unset FDI_RX_MISC pwrdn lanes */
-		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
-		temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
-		intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), temp);
-		intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));
-
-		/* Wait for FDI auto training time */
-		udelay(5);
-
-		temp = intel_de_read(dev_priv, DP_TP_STATUS(PORT_E));
-		if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "FDI link training done on step %d\n", i);
-			break;
-		}
-
-		/*
-		 * Leave things enabled even if we failed to train FDI.
-		 * Results in less fireworks from the state checker.
-		 */
-		if (i == ARRAY_SIZE(hsw_ddi_translations_fdi) * 2 - 1) {
-			drm_err(&dev_priv->drm, "FDI link training failed!\n");
-			break;
-		}
-
-		rx_ctl_val &= ~FDI_RX_ENABLE;
-		intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
-		intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
-
-		temp = intel_de_read(dev_priv, DDI_BUF_CTL(PORT_E));
-		temp &= ~DDI_BUF_CTL_ENABLE;
-		intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E), temp);
-		intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
-
-		/* Disable DP_TP_CTL and FDI_RX_CTL and retry */
-		temp = intel_de_read(dev_priv, DP_TP_CTL(PORT_E));
-		temp &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
-		temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
-		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
-		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
-
-		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
-
-		/* Reset FDI_RX_MISC pwrdn lanes */
-		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
-		temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
-		temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
-		intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), temp);
-		intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));
-	}
-
-	/* Enable normal pixel sending for FDI */
-	intel_de_write(dev_priv, DP_TP_CTL(PORT_E),
-		       DP_TP_CTL_FDI_AUTOTRAIN |
-		       DP_TP_CTL_LINK_TRAIN_NORMAL |
-		       DP_TP_CTL_ENHANCED_FRAME_ENABLE |
-		       DP_TP_CTL_ENABLE);
-}
-
 static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
 				      const struct intel_crtc_state *crtc_state)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h
index dcc711cfe4fe..e42b6bd05e01 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.h
+++ b/drivers/gpu/drm/i915/display/intel_ddi.h
@@ -9,6 +9,12 @@
 #include "intel_display.h"
 #include "i915_reg.h"
 
+struct ddi_buf_trans {
+	u32 trans1;	/* balance leg enable, de-emph level */
+	u32 trans2;	/* vref sel, vswing */
+	u8 i_boost;	/* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */
+};
+
 struct drm_connector_state;
 struct drm_i915_private;
 struct intel_connector;
@@ -17,6 +23,7 @@ struct intel_crtc_state;
 struct intel_dp;
 struct intel_dpll_hw_state;
 struct intel_encoder;
+struct intel_shared_dpll;
 enum transcoder;
 
 i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
@@ -27,8 +34,11 @@ void intel_ddi_fdi_post_disable(struct intel_atomic_state *state,
 				struct intel_encoder *intel_encoder,
 				const struct intel_crtc_state *old_crtc_state,
 				const struct drm_connector_state *old_conn_state);
-void hsw_fdi_link_train(struct intel_encoder *encoder,
-			const struct intel_crtc_state *crtc_state);
+u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll);
+void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
+				  const struct intel_crtc_state *crtc_state);
+void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
+			     enum port port);
 void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port);
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
 void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 731ea6f7777a..723772802d7e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -686,6 +686,8 @@ void ilk_fdi_disable(struct intel_crtc *crtc);
 void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
 void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state);
 void intel_init_fdi_hook(struct drm_i915_private *dev_priv);
+void hsw_fdi_link_train(struct intel_encoder *encoder,
+			const struct intel_crtc_state *crtc_state);
 
 /* modesetting */
 void intel_modeset_init_hw(struct drm_i915_private *i915);
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index bf4ef84686ef..22865091d285 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -4,6 +4,19 @@
  */
 #include "intel_atomic.h"
 #include "intel_display_types.h"
+#include "intel_ddi.h"
+
+static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = {
+	{ 0x00FFFFFF, 0x0007000E, 0x0 },
+	{ 0x00D75FFF, 0x000F000A, 0x0 },
+	{ 0x00C30FFF, 0x00060006, 0x0 },
+	{ 0x00AAAFFF, 0x001E0000, 0x0 },
+	{ 0x00FFFFFF, 0x000F000A, 0x0 },
+	{ 0x00D75FFF, 0x00160004, 0x0 },
+	{ 0x00C30FFF, 0x001E0000, 0x0 },
+	{ 0x00FFFFFF, 0x00060006, 0x0 },
+	{ 0x00D75FFF, 0x001E0000, 0x0 },
+};
 
 /* units of 100MHz */
 static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
@@ -549,6 +562,140 @@ static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,
 	drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");
 }
 
+/* Starting with Haswell, different DDI ports can work in FDI mode for
+ * connection to the PCH-located connectors. For this, it is necessary to train
+ * both the DDI port and PCH receiver for the desired DDI buffer settings.
+ *
+ * The recommended port to work in FDI mode is DDI E, which we use here. Also,
+ * please note that when FDI mode is active on DDI E, it shares 2 lines with
+ * DDI A (which is used for eDP)
+ */
+void hsw_fdi_link_train(struct intel_encoder *encoder,
+			const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	u32 temp, i, rx_ctl_val, ddi_pll_sel;
+
+	intel_prepare_dp_ddi_buffers(encoder, crtc_state);
+
+	/* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
+	 * mode set "sequence for CRT port" document:
+	 * - TP1 to TP2 time with the default value
+	 * - FDI delay to 90h
+	 *
+	 * WaFDIAutoLinkSetTimingOverrride:hsw
+	 */
+	intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A),
+		       FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2) | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+
+	/* Enable the PCH Receiver FDI PLL */
+	rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
+		     FDI_RX_PLL_ENABLE |
+		     FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
+	intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
+	intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
+	udelay(220);
+
+	/* Switch from Rawclk to PCDclk */
+	rx_ctl_val |= FDI_PCDCLK;
+	intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
+
+	/* Configure Port Clock Select */
+	ddi_pll_sel = hsw_pll_to_ddi_pll_sel(crtc_state->shared_dpll);
+	intel_de_write(dev_priv, PORT_CLK_SEL(PORT_E), ddi_pll_sel);
+	drm_WARN_ON(&dev_priv->drm, ddi_pll_sel != PORT_CLK_SEL_SPLL);
+
+	/* Start the training iterating through available voltages and emphasis,
+	 * testing each value twice. */
+	for (i = 0; i < ARRAY_SIZE(hsw_ddi_translations_fdi) * 2; i++) {
+		/* Configure DP_TP_CTL with auto-training */
+		intel_de_write(dev_priv, DP_TP_CTL(PORT_E),
+			       DP_TP_CTL_FDI_AUTOTRAIN |
+			       DP_TP_CTL_ENHANCED_FRAME_ENABLE |
+			       DP_TP_CTL_LINK_TRAIN_PAT1 |
+			       DP_TP_CTL_ENABLE);
+
+		/* Configure and enable DDI_BUF_CTL for DDI E with next voltage.
+		 * DDI E does not support port reversal, the functionality is
+		 * achieved on the PCH side in FDI_RX_CTL, so no need to set the
+		 * port reversal bit */
+		intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E),
+			       DDI_BUF_CTL_ENABLE | ((crtc_state->fdi_lanes - 1) << 1) | DDI_BUF_TRANS_SELECT(i / 2));
+		intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
+
+		udelay(600);
+
+		/* Program PCH FDI Receiver TU */
+		intel_de_write(dev_priv, FDI_RX_TUSIZE1(PIPE_A), TU_SIZE(64));
+
+		/* Enable PCH FDI Receiver with auto-training */
+		rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO;
+		intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
+		intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
+
+		/* Wait for FDI receiver lane calibration */
+		udelay(30);
+
+		/* Unset FDI_RX_MISC pwrdn lanes */
+		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
+		temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
+		intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), temp);
+		intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));
+
+		/* Wait for FDI auto training time */
+		udelay(5);
+
+		temp = intel_de_read(dev_priv, DP_TP_STATUS(PORT_E));
+		if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "FDI link training done on step %d\n", i);
+			break;
+		}
+
+		/*
+		 * Leave things enabled even if we failed to train FDI.
+		 * Results in less fireworks from the state checker.
+		 */
+		if (i == ARRAY_SIZE(hsw_ddi_translations_fdi) * 2 - 1) {
+			drm_err(&dev_priv->drm, "FDI link training failed!\n");
+			break;
+		}
+
+		rx_ctl_val &= ~FDI_RX_ENABLE;
+		intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
+		intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
+
+		temp = intel_de_read(dev_priv, DDI_BUF_CTL(PORT_E));
+		temp &= ~DDI_BUF_CTL_ENABLE;
+		intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E), temp);
+		intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
+
+		/* Disable DP_TP_CTL and FDI_RX_CTL and retry */
+		temp = intel_de_read(dev_priv, DP_TP_CTL(PORT_E));
+		temp &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
+		temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
+		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
+		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
+
+		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
+
+		/* Reset FDI_RX_MISC pwrdn lanes */
+		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
+		temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
+		temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
+		intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), temp);
+		intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));
+	}
+
+	/* Enable normal pixel sending for FDI */
+	intel_de_write(dev_priv, DP_TP_CTL(PORT_E),
+		       DP_TP_CTL_FDI_AUTOTRAIN |
+		       DP_TP_CTL_LINK_TRAIN_NORMAL |
+		       DP_TP_CTL_ENHANCED_FRAME_ENABLE |
+		       DP_TP_CTL_ENABLE);
+}
+
 void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] [PATCH 9/9] drm/i915: migrate skl planes code new file
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (7 preceding siblings ...)
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 8/9] drm/i915: migrate hsw fdi code to new file Dave Airlie
@ 2020-12-10  4:17 ` Dave Airlie
  2020-12-10  4:32 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header Patchwork
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  4:17 UTC (permalink / raw)
  To: intel-gfx

From: Dave Airlie <airlied@redhat.com>

rework the plane init calls to do the gen test one level higher.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/Makefile                 |    1 +
 drivers/gpu/drm/i915/display/intel_crtc.c     |   16 +-
 .../gpu/drm/i915/display/intel_gen9_plane.c   | 1427 +++++++++++++++++
 drivers/gpu/drm/i915/display/intel_sprite.c   | 1417 +---------------
 4 files changed, 1449 insertions(+), 1412 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_gen9_plane.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index d6003b676f0d..eb56fe154c77 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -210,6 +210,7 @@ i915-y += \
 	display/intel_fifo_underrun.o \
 	display/intel_frontbuffer.o \
 	display/intel_global_state.o \
+	display/intel_gen9_plane.o \
 	display/intel_hdcp.o \
 	display/intel_hotplug.o \
 	display/intel_lpe_audio.o \
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 75a79f18cee2..f12c1ddc8d56 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -615,10 +615,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 	int num_formats;
 	int ret, zpos;
 
-	if (INTEL_GEN(dev_priv) >= 9)
-		return skl_universal_plane_create(dev_priv, pipe,
-						  PLANE_PRIMARY);
-
 	plane = intel_plane_alloc();
 	if (IS_ERR(plane))
 		return plane;
@@ -869,7 +865,11 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 	crtc->pipe = pipe;
 	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
 
-	primary = intel_primary_plane_create(dev_priv, pipe);
+	if (INTEL_GEN(dev_priv) >= 9)
+		primary = skl_universal_plane_create(dev_priv, pipe,
+						     PLANE_PRIMARY);
+	else
+		primary = intel_primary_plane_create(dev_priv, pipe);
 	if (IS_ERR(primary)) {
 		ret = PTR_ERR(primary);
 		goto fail;
@@ -879,7 +879,11 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 	for_each_sprite(dev_priv, pipe, sprite) {
 		struct intel_plane *plane;
 
-		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
+		if (INTEL_GEN(dev_priv) >= 9)
+			plane = skl_universal_plane_create(dev_priv, pipe,
+							   PLANE_SPRITE0 + sprite);
+		else
+			plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
 		if (IS_ERR(plane)) {
 			ret = PTR_ERR(plane);
 			goto fail;
diff --git a/drivers/gpu/drm/i915/display/intel_gen9_plane.c b/drivers/gpu/drm/i915/display/intel_gen9_plane.c
new file mode 100644
index 000000000000..c76ff50d08c2
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_gen9_plane.c
@@ -0,0 +1,1427 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane_helper.h>
+
+#include "i915_drv.h"
+#include "intel_atomic_plane.h"
+#include "intel_display_types.h"
+#include "intel_pm.h"
+#include "intel_psr.h"
+#include "intel_sprite.h"
+
+static const u32 skl_plane_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_XRGB16161616F,
+	DRM_FORMAT_XBGR16161616F,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_XYUV8888,
+};
+
+static const u32 skl_planar_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_XRGB16161616F,
+	DRM_FORMAT_XBGR16161616F,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_XYUV8888,
+};
+
+static const u32 glk_planar_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_XRGB16161616F,
+	DRM_FORMAT_XBGR16161616F,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_XYUV8888,
+	DRM_FORMAT_P010,
+	DRM_FORMAT_P012,
+	DRM_FORMAT_P016,
+};
+
+static const u32 icl_sdr_y_plane_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_Y210,
+	DRM_FORMAT_Y212,
+	DRM_FORMAT_Y216,
+	DRM_FORMAT_XYUV8888,
+	DRM_FORMAT_XVYU2101010,
+	DRM_FORMAT_XVYU12_16161616,
+	DRM_FORMAT_XVYU16161616,
+};
+
+static const u32 icl_sdr_uv_plane_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_P010,
+	DRM_FORMAT_P012,
+	DRM_FORMAT_P016,
+	DRM_FORMAT_Y210,
+	DRM_FORMAT_Y212,
+	DRM_FORMAT_Y216,
+	DRM_FORMAT_XYUV8888,
+	DRM_FORMAT_XVYU2101010,
+	DRM_FORMAT_XVYU12_16161616,
+	DRM_FORMAT_XVYU16161616,
+};
+
+static const u32 icl_hdr_plane_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_XRGB16161616F,
+	DRM_FORMAT_XBGR16161616F,
+	DRM_FORMAT_ARGB16161616F,
+	DRM_FORMAT_ABGR16161616F,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_P010,
+	DRM_FORMAT_P012,
+	DRM_FORMAT_P016,
+	DRM_FORMAT_Y210,
+	DRM_FORMAT_Y212,
+	DRM_FORMAT_Y216,
+	DRM_FORMAT_XYUV8888,
+	DRM_FORMAT_XVYU2101010,
+	DRM_FORMAT_XVYU12_16161616,
+	DRM_FORMAT_XVYU16161616,
+};
+
+static const u64 skl_plane_format_modifiers_noccs[] = {
+	I915_FORMAT_MOD_Yf_TILED,
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static const u64 skl_plane_format_modifiers_ccs[] = {
+	I915_FORMAT_MOD_Yf_TILED_CCS,
+	I915_FORMAT_MOD_Y_TILED_CCS,
+	I915_FORMAT_MOD_Yf_TILED,
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
+	I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
+	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
+	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+
+static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
+{
+	if (IS_ROCKETLAKE(i915))
+		return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
+	else
+		return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
+}
+
+bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
+			 enum plane_id plane_id)
+{
+	return INTEL_GEN(dev_priv) >= 11 &&
+		icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
+}
+
+bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
+{
+	return INTEL_GEN(dev_priv) >= 11 &&
+		icl_hdr_plane_mask() & BIT(plane_id);
+}
+
+static void
+skl_plane_ratio(const struct intel_crtc_state *crtc_state,
+		const struct intel_plane_state *plane_state,
+		unsigned int *num, unsigned int *den)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+
+	if (fb->format->cpp[0] == 8) {
+		if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
+			*num = 10;
+			*den = 8;
+		} else {
+			*num = 9;
+			*den = 8;
+		}
+	} else {
+		*num = 1;
+		*den = 1;
+	}
+}
+
+static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
+			       const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
+	unsigned int num, den;
+	unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+
+	skl_plane_ratio(crtc_state, plane_state, &num, &den);
+
+	/* two pixels per clock on glk+ */
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+		den *= 2;
+
+	return DIV_ROUND_UP(pixel_rate * num, den);
+}
+
+static int skl_plane_max_width(const struct drm_framebuffer *fb,
+			       int color_plane,
+			       unsigned int rotation)
+{
+	int cpp = fb->format->cpp[color_plane];
+
+	switch (fb->modifier) {
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+		/*
+		 * Validated limit is 4k, but has 5k should
+		 * work apart from the following features:
+		 * - Ytile (already limited to 4k)
+		 * - FP16 (already limited to 4k)
+		 * - render compression (already limited to 4k)
+		 * - KVMR sprite and cursor (don't care)
+		 * - horizontal panning (TODO verify this)
+		 * - pipe and plane scaling (TODO verify this)
+		 */
+		if (cpp == 8)
+			return 4096;
+		else
+			return 5120;
+	case I915_FORMAT_MOD_Y_TILED_CCS:
+	case I915_FORMAT_MOD_Yf_TILED_CCS:
+	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
+		/* FIXME AUX plane? */
+	case I915_FORMAT_MOD_Y_TILED:
+	case I915_FORMAT_MOD_Yf_TILED:
+		if (cpp == 8)
+			return 2048;
+		else
+			return 4096;
+	default:
+		MISSING_CASE(fb->modifier);
+		return 2048;
+	}
+}
+
+static int glk_plane_max_width(const struct drm_framebuffer *fb,
+			       int color_plane,
+			       unsigned int rotation)
+{
+	int cpp = fb->format->cpp[color_plane];
+
+	switch (fb->modifier) {
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+		if (cpp == 8)
+			return 4096;
+		else
+			return 5120;
+	case I915_FORMAT_MOD_Y_TILED_CCS:
+	case I915_FORMAT_MOD_Yf_TILED_CCS:
+		/* FIXME AUX plane? */
+	case I915_FORMAT_MOD_Y_TILED:
+	case I915_FORMAT_MOD_Yf_TILED:
+		if (cpp == 8)
+			return 2048;
+		else
+			return 5120;
+	default:
+		MISSING_CASE(fb->modifier);
+		return 2048;
+	}
+}
+
+static int icl_plane_min_width(const struct drm_framebuffer *fb,
+			       int color_plane,
+			       unsigned int rotation)
+{
+	/* Wa_14011264657, Wa_14011050563: gen11+ */
+	switch (fb->format->format) {
+	case DRM_FORMAT_C8:
+		return 18;
+	case DRM_FORMAT_RGB565:
+		return 10;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_XVYU2101010:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
+		return 6;
+	case DRM_FORMAT_NV12:
+		return 20;
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+		return 12;
+	case DRM_FORMAT_XRGB16161616F:
+	case DRM_FORMAT_XBGR16161616F:
+	case DRM_FORMAT_ARGB16161616F:
+	case DRM_FORMAT_ABGR16161616F:
+	case DRM_FORMAT_XVYU12_16161616:
+	case DRM_FORMAT_XVYU16161616:
+		return 4;
+	default:
+		return 1;
+	}
+}
+
+static int icl_plane_max_width(const struct drm_framebuffer *fb,
+			       int color_plane,
+			       unsigned int rotation)
+{
+	return 5120;
+}
+
+static int skl_plane_max_height(const struct drm_framebuffer *fb,
+				int color_plane,
+				unsigned int rotation)
+{
+	return 4096;
+}
+
+static int icl_plane_max_height(const struct drm_framebuffer *fb,
+				int color_plane,
+				unsigned int rotation)
+{
+	return 4320;
+}
+
+static unsigned int
+skl_plane_max_stride(struct intel_plane *plane,
+		     u32 pixel_format, u64 modifier,
+		     unsigned int rotation)
+{
+	const struct drm_format_info *info = drm_format_info(pixel_format);
+	int cpp = info->cpp[0];
+
+	/*
+	 * "The stride in bytes must not exceed the
+	 * of the size of 8K pixels and 32K bytes."
+	 */
+	if (drm_rotation_90_or_270(rotation))
+		return min(8192, 32768 / cpp);
+	else
+		return min(8192 * cpp, 32768);
+}
+
+static void
+skl_program_scaler(struct intel_plane *plane,
+		   const struct intel_crtc_state *crtc_state,
+		   const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	enum pipe pipe = plane->pipe;
+	int scaler_id = plane_state->scaler_id;
+	const struct intel_scaler *scaler =
+		&crtc_state->scaler_state.scalers[scaler_id];
+	int crtc_x = plane_state->uapi.dst.x1;
+	int crtc_y = plane_state->uapi.dst.y1;
+	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
+	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
+	u16 y_hphase, uv_rgb_hphase;
+	u16 y_vphase, uv_rgb_vphase;
+	int hscale, vscale;
+	u32 ps_ctrl;
+
+	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
+				      &plane_state->uapi.dst,
+				      0, INT_MAX);
+	vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
+				      &plane_state->uapi.dst,
+				      0, INT_MAX);
+
+	/* TODO: handle sub-pixel coordinates */
+	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
+	    !icl_is_hdr_plane(dev_priv, plane->id)) {
+		y_hphase = skl_scaler_calc_phase(1, hscale, false);
+		y_vphase = skl_scaler_calc_phase(1, vscale, false);
+
+		/* MPEG2 chroma siting convention */
+		uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
+		uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
+	} else {
+		/* not used */
+		y_hphase = 0;
+		y_vphase = 0;
+
+		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
+		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
+	}
+
+	ps_ctrl = skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0);
+	ps_ctrl |= PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode;
+
+	skl_scaler_setup_filter(dev_priv, pipe, scaler_id, 0,
+				plane_state->hw.scaling_filter);
+
+	intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
+	intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, scaler_id),
+			  PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
+	intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id),
+			  PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
+	intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, scaler_id),
+			  (crtc_x << 16) | crtc_y);
+	intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, scaler_id),
+			  (crtc_w << 16) | crtc_h);
+}
+
+/* Preoffset values for YUV to RGB Conversion */
+#define PREOFF_YUV_TO_RGB_HI		0x1800
+#define PREOFF_YUV_TO_RGB_ME		0x1F00
+#define PREOFF_YUV_TO_RGB_LO		0x1800
+
+#define  ROFF(x)          (((x) & 0xffff) << 16)
+#define  GOFF(x)          (((x) & 0xffff) << 0)
+#define  BOFF(x)          (((x) & 0xffff) << 16)
+
+static void
+icl_program_input_csc(struct intel_plane *plane,
+		      const struct intel_crtc_state *crtc_state,
+		      const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum pipe pipe = plane->pipe;
+	enum plane_id plane_id = plane->id;
+
+	static const u16 input_csc_matrix[][9] = {
+		/*
+		 * BT.601 full range YCbCr -> full range RGB
+		 * The matrix required is :
+		 * [1.000, 0.000, 1.371,
+		 *  1.000, -0.336, -0.698,
+		 *  1.000, 1.732, 0.0000]
+		 */
+		[DRM_COLOR_YCBCR_BT601] = {
+			0x7AF8, 0x7800, 0x0,
+			0x8B28, 0x7800, 0x9AC0,
+			0x0, 0x7800, 0x7DD8,
+		},
+		/*
+		 * BT.709 full range YCbCr -> full range RGB
+		 * The matrix required is :
+		 * [1.000, 0.000, 1.574,
+		 *  1.000, -0.187, -0.468,
+		 *  1.000, 1.855, 0.0000]
+		 */
+		[DRM_COLOR_YCBCR_BT709] = {
+			0x7C98, 0x7800, 0x0,
+			0x9EF8, 0x7800, 0xAC00,
+			0x0, 0x7800,  0x7ED8,
+		},
+		/*
+		 * BT.2020 full range YCbCr -> full range RGB
+		 * The matrix required is :
+		 * [1.000, 0.000, 1.474,
+		 *  1.000, -0.1645, -0.5713,
+		 *  1.000, 1.8814, 0.0000]
+		 */
+		[DRM_COLOR_YCBCR_BT2020] = {
+			0x7BC8, 0x7800, 0x0,
+			0x8928, 0x7800, 0xAA88,
+			0x0, 0x7800, 0x7F10,
+		},
+	};
+
+	/* Matrix for Limited Range to Full Range Conversion */
+	static const u16 input_csc_matrix_lr[][9] = {
+		/*
+		 * BT.601 Limted range YCbCr -> full range RGB
+		 * The matrix required is :
+		 * [1.164384, 0.000, 1.596027,
+		 *  1.164384, -0.39175, -0.812813,
+		 *  1.164384, 2.017232, 0.0000]
+		 */
+		[DRM_COLOR_YCBCR_BT601] = {
+			0x7CC8, 0x7950, 0x0,
+			0x8D00, 0x7950, 0x9C88,
+			0x0, 0x7950, 0x6810,
+		},
+		/*
+		 * BT.709 Limited range YCbCr -> full range RGB
+		 * The matrix required is :
+		 * [1.164384, 0.000, 1.792741,
+		 *  1.164384, -0.213249, -0.532909,
+		 *  1.164384, 2.112402, 0.0000]
+		 */
+		[DRM_COLOR_YCBCR_BT709] = {
+			0x7E58, 0x7950, 0x0,
+			0x8888, 0x7950, 0xADA8,
+			0x0, 0x7950,  0x6870,
+		},
+		/*
+		 * BT.2020 Limited range YCbCr -> full range RGB
+		 * The matrix required is :
+		 * [1.164, 0.000, 1.678,
+		 *  1.164, -0.1873, -0.6504,
+		 *  1.164, 2.1417, 0.0000]
+		 */
+		[DRM_COLOR_YCBCR_BT2020] = {
+			0x7D70, 0x7950, 0x0,
+			0x8A68, 0x7950, 0xAC00,
+			0x0, 0x7950, 0x6890,
+		},
+	};
+	const u16 *csc;
+
+	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
+		csc = input_csc_matrix[plane_state->hw.color_encoding];
+	else
+		csc = input_csc_matrix_lr[plane_state->hw.color_encoding];
+
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
+			  ROFF(csc[0]) | GOFF(csc[1]));
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
+			  BOFF(csc[2]));
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
+			  ROFF(csc[3]) | GOFF(csc[4]));
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
+			  BOFF(csc[5]));
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
+			  ROFF(csc[6]) | GOFF(csc[7]));
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
+			  BOFF(csc[8]));
+
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
+			  PREOFF_YUV_TO_RGB_HI);
+	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
+		intel_de_write_fw(dev_priv,
+				  PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
+				  0);
+	else
+		intel_de_write_fw(dev_priv,
+				  PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
+				  PREOFF_YUV_TO_RGB_ME);
+	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
+			  PREOFF_YUV_TO_RGB_LO);
+	intel_de_write_fw(dev_priv,
+			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
+	intel_de_write_fw(dev_priv,
+			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
+	intel_de_write_fw(dev_priv,
+			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
+}
+
+static void
+skl_plane_async_flip(struct intel_plane *plane,
+		     const struct intel_crtc_state *crtc_state,
+		     const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	unsigned long irqflags;
+	enum plane_id plane_id = plane->id;
+	enum pipe pipe = plane->pipe;
+	u32 surf_addr = plane_state->color_plane[0].offset;
+	u32 plane_ctl = plane_state->ctl;
+
+	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
+	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
+			  intel_plane_ggtt_offset(plane_state) + surf_addr);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static void
+skl_program_plane(struct intel_plane *plane,
+		  const struct intel_crtc_state *crtc_state,
+		  const struct intel_plane_state *plane_state,
+		  int color_plane)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum plane_id plane_id = plane->id;
+	enum pipe pipe = plane->pipe;
+	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
+	u32 surf_addr = plane_state->color_plane[color_plane].offset;
+	u32 stride = skl_plane_stride(plane_state, color_plane);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	int aux_plane = intel_main_to_aux_plane(fb, color_plane);
+	int crtc_x = plane_state->uapi.dst.x1;
+	int crtc_y = plane_state->uapi.dst.y1;
+	u32 x = plane_state->color_plane[color_plane].x;
+	u32 y = plane_state->color_plane[color_plane].y;
+	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
+	u8 alpha = plane_state->hw.alpha >> 8;
+	u32 plane_color_ctl = 0, aux_dist = 0;
+	unsigned long irqflags;
+	u32 keymsk, keymax;
+	u32 plane_ctl = plane_state->ctl;
+
+	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
+
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+		plane_color_ctl = plane_state->color_ctl |
+			glk_plane_color_ctl_crtc(crtc_state);
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+
+	keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
+
+	keymsk = key->channel_mask & 0x7ffffff;
+	if (alpha < 0xff)
+		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
+
+	/* The scaler will handle the output position */
+	if (plane_state->scaler_id >= 0) {
+		crtc_x = 0;
+		crtc_y = 0;
+	}
+
+	if (aux_plane) {
+		aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
+
+		if (INTEL_GEN(dev_priv) < 12)
+			aux_dist |= skl_plane_stride(plane_state, aux_plane);
+	}
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
+	intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
+			  (crtc_y << 16) | crtc_x);
+	intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
+			  (src_h << 16) | src_w);
+
+	intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
+
+	if (icl_is_hdr_plane(dev_priv, plane_id))
+		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
+				  plane_state->cus_ctl);
+
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+		intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
+				  plane_color_ctl);
+
+	if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
+		icl_program_input_csc(plane, crtc_state, plane_state);
+
+	skl_write_plane_wm(plane, crtc_state);
+
+	intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
+			  key->min_value);
+	intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
+	intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
+
+	intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
+			  (y << 16) | x);
+
+	if (INTEL_GEN(dev_priv) < 11)
+		intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
+				  (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);
+
+	if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
+		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
+
+	/*
+	 * The control register self-arms if the plane was previously
+	 * disabled. Try to make the plane enable atomic by writing
+	 * the control register just before the surface register.
+	 */
+	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
+	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
+			  intel_plane_ggtt_offset(plane_state) + surf_addr);
+
+	if (plane_state->scaler_id >= 0)
+		skl_program_scaler(plane, crtc_state, plane_state);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static void
+skl_update_plane(struct intel_plane *plane,
+		 const struct intel_crtc_state *crtc_state,
+		 const struct intel_plane_state *plane_state)
+{
+	int color_plane = 0;
+
+	if (plane_state->planar_linked_plane && !plane_state->planar_slave)
+		/* Program the UV plane on planar master */
+		color_plane = 1;
+
+	skl_program_plane(plane, crtc_state, plane_state, color_plane);
+}
+static void
+skl_disable_plane(struct intel_plane *plane,
+		  const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum plane_id plane_id = plane->id;
+	enum pipe pipe = plane->pipe;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	if (icl_is_hdr_plane(dev_priv, plane_id))
+		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
+
+	skl_write_plane_wm(plane, crtc_state);
+
+	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
+	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static bool
+skl_plane_get_hw_state(struct intel_plane *plane,
+		       enum pipe *pipe)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum intel_display_power_domain power_domain;
+	enum plane_id plane_id = plane->id;
+	intel_wakeref_t wakeref;
+	bool ret;
+
+	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
+		return false;
+
+	ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
+
+	*pipe = plane->pipe;
+
+	intel_display_power_put(dev_priv, power_domain, wakeref);
+
+	return ret;
+}
+
+static bool intel_format_is_p01x(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
+			      const struct intel_plane_state *plane_state)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	unsigned int rotation = plane_state->hw.rotation;
+	struct drm_format_name_buf format_name;
+
+	if (!fb)
+		return 0;
+
+	if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
+	    is_ccs_modifier(fb->modifier)) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "RC support only with 0/180 degree rotation (%x)\n",
+			    rotation);
+		return -EINVAL;
+	}
+
+	if (rotation & DRM_MODE_REFLECT_X &&
+	    fb->modifier == DRM_FORMAT_MOD_LINEAR) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "horizontal flip is not supported with linear surface formats\n");
+		return -EINVAL;
+	}
+
+	if (drm_rotation_90_or_270(rotation)) {
+		if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
+		    fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
+			drm_dbg_kms(&dev_priv->drm,
+				    "Y/Yf tiling required for 90/270!\n");
+			return -EINVAL;
+		}
+
+		/*
+		 * 90/270 is not allowed with RGB64 16:16:16:16 and
+		 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
+		 */
+		switch (fb->format->format) {
+		case DRM_FORMAT_RGB565:
+			if (INTEL_GEN(dev_priv) >= 11)
+				break;
+			fallthrough;
+		case DRM_FORMAT_C8:
+		case DRM_FORMAT_XRGB16161616F:
+		case DRM_FORMAT_XBGR16161616F:
+		case DRM_FORMAT_ARGB16161616F:
+		case DRM_FORMAT_ABGR16161616F:
+		case DRM_FORMAT_Y210:
+		case DRM_FORMAT_Y212:
+		case DRM_FORMAT_Y216:
+		case DRM_FORMAT_XVYU12_16161616:
+		case DRM_FORMAT_XVYU16161616:
+			drm_dbg_kms(&dev_priv->drm,
+				    "Unsupported pixel format %s for 90/270!\n",
+				    drm_get_format_name(fb->format->format,
+							&format_name));
+			return -EINVAL;
+		default:
+			break;
+		}
+	}
+
+	/* Y-tiling is not supported in IF-ID Interlace mode */
+	if (crtc_state->hw.enable &&
+	    crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
+	    (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
+	     fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
+	     fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
+	     fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
+	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
+	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "Y/Yf tiling not supported in IF-ID mode\n");
+		return -EINVAL;
+	}
+
+	/* Wa_1606054188:tgl */
+	if (IS_TIGERLAKE(dev_priv) &&
+	    plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
+	    intel_format_is_p01x(fb->format->format)) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "Source color keying not supported with P01x formats\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
+					   const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->uapi.plane->dev);
+	int crtc_x = plane_state->uapi.dst.x1;
+	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
+	int pipe_src_w = crtc_state->pipe_src_w;
+
+	/*
+	 * Display WA #1175: cnl,glk
+	 * Planes other than the cursor may cause FIFO underflow and display
+	 * corruption if starting less than 4 pixels from the right edge of
+	 * the screen.
+	 * Besides the above WA fix the similar problem, where planes other
+	 * than the cursor ending less than 4 pixels from the left edge of the
+	 * screen may cause FIFO underflow and display corruption.
+	 */
+	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
+	    (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "requested plane X %s position %d invalid (valid range %d-%d)\n",
+			    crtc_x + crtc_w < 4 ? "end" : "start",
+			    crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
+			    4, pipe_src_w - 4);
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
+{
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	unsigned int rotation = plane_state->hw.rotation;
+	int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+
+	/* Display WA #1106 */
+	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
+	    src_w & 3 &&
+	    (rotation == DRM_MODE_ROTATE_270 ||
+	     rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
+		DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
+			       const struct drm_framebuffer *fb)
+{
+	/*
+	 * We don't yet know the final source width nor
+	 * whether we can use the HQ scaler mode. Assume
+	 * the best case.
+	 * FIXME need to properly check this later.
+	 */
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
+	    !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
+		return 0x30000 - 1;
+	else
+		return 0x20000 - 1;
+}
+
+static bool intel_fb_scalable(const struct drm_framebuffer *fb)
+{
+	if (!fb)
+		return false;
+
+	switch (fb->format->format) {
+	case DRM_FORMAT_C8:
+		return false;
+	case DRM_FORMAT_XRGB16161616F:
+	case DRM_FORMAT_ARGB16161616F:
+	case DRM_FORMAT_XBGR16161616F:
+	case DRM_FORMAT_ABGR16161616F:
+		return INTEL_GEN(to_i915(fb->dev)) >= 11;
+	default:
+		return true;
+	}
+}
+
+static int skl_plane_check(struct intel_crtc_state *crtc_state,
+			   struct intel_plane_state *plane_state)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
+	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
+	int ret;
+
+	ret = skl_plane_check_fb(crtc_state, plane_state);
+	if (ret)
+		return ret;
+
+	/* use scaler when colorkey is not required */
+	if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
+		min_scale = 1;
+		max_scale = skl_plane_max_scale(dev_priv, fb);
+	}
+
+	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
+						min_scale, max_scale, true);
+	if (ret)
+		return ret;
+
+	ret = skl_check_plane_surface(plane_state);
+	if (ret)
+		return ret;
+
+	if (!plane_state->uapi.visible)
+		return 0;
+
+	ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
+	if (ret)
+		return ret;
+
+	ret = intel_plane_check_src_coordinates(plane_state);
+	if (ret)
+		return ret;
+
+	ret = skl_plane_check_nv12_rotation(plane_state);
+	if (ret)
+		return ret;
+
+	/* HW only has 8 bits pixel precision, disable plane if invisible */
+	if (!(plane_state->hw.alpha >> 8))
+		plane_state->uapi.visible = false;
+
+	plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
+
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+		plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
+							     plane_state);
+
+	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
+	    icl_is_hdr_plane(dev_priv, plane->id))
+		/* Enable and use MPEG-2 chroma siting */
+		plane_state->cus_ctl = PLANE_CUS_ENABLE |
+			PLANE_CUS_HPHASE_0 |
+			PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
+	else
+		plane_state->cus_ctl = 0;
+
+	return 0;
+}
+
+static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
+			      enum pipe pipe, enum plane_id plane_id)
+{
+	if (!HAS_FBC(dev_priv))
+		return false;
+
+	return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
+}
+
+static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
+				 enum pipe pipe, enum plane_id plane_id)
+{
+	/* Display WA #0870: skl, bxt */
+	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
+		return false;
+
+	if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
+		return false;
+
+	if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
+		return false;
+
+	return true;
+}
+
+static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
+					enum pipe pipe, enum plane_id plane_id,
+					int *num_formats)
+{
+	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
+		*num_formats = ARRAY_SIZE(skl_planar_formats);
+		return skl_planar_formats;
+	} else {
+		*num_formats = ARRAY_SIZE(skl_plane_formats);
+		return skl_plane_formats;
+	}
+}
+
+static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
+					enum pipe pipe, enum plane_id plane_id,
+					int *num_formats)
+{
+	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
+		*num_formats = ARRAY_SIZE(glk_planar_formats);
+		return glk_planar_formats;
+	} else {
+		*num_formats = ARRAY_SIZE(skl_plane_formats);
+		return skl_plane_formats;
+	}
+}
+
+static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
+					enum pipe pipe, enum plane_id plane_id,
+					int *num_formats)
+{
+	if (icl_is_hdr_plane(dev_priv, plane_id)) {
+		*num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
+		return icl_hdr_plane_formats;
+	} else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
+		*num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
+		return icl_sdr_y_plane_formats;
+	} else {
+		*num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
+		return icl_sdr_uv_plane_formats;
+	}
+}
+
+static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
+			      enum pipe pipe, enum plane_id plane_id)
+{
+	if (plane_id == PLANE_CURSOR)
+		return false;
+
+	if (INTEL_GEN(dev_priv) >= 10)
+		return true;
+
+	if (IS_GEMINILAKE(dev_priv))
+		return pipe != PIPE_C;
+
+	return pipe != PIPE_C &&
+		(plane_id == PLANE_PRIMARY ||
+		 plane_id == PLANE_SPRITE0);
+}
+
+static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
+					   u32 format, u64 modifier)
+{
+	struct intel_plane *plane = to_intel_plane(_plane);
+
+	switch (modifier) {
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+	case I915_FORMAT_MOD_Y_TILED:
+	case I915_FORMAT_MOD_Yf_TILED:
+		break;
+	case I915_FORMAT_MOD_Y_TILED_CCS:
+	case I915_FORMAT_MOD_Yf_TILED_CCS:
+		if (!plane->has_ccs)
+			return false;
+		break;
+	default:
+		return false;
+	}
+
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+		if (is_ccs_modifier(modifier))
+			return true;
+		fallthrough;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_XYUV8888:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+	case DRM_FORMAT_XVYU2101010:
+		if (modifier == I915_FORMAT_MOD_Yf_TILED)
+			return true;
+		fallthrough;
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_XBGR16161616F:
+	case DRM_FORMAT_ABGR16161616F:
+	case DRM_FORMAT_XRGB16161616F:
+	case DRM_FORMAT_ARGB16161616F:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
+	case DRM_FORMAT_XVYU12_16161616:
+	case DRM_FORMAT_XVYU16161616:
+		if (modifier == DRM_FORMAT_MOD_LINEAR ||
+		    modifier == I915_FORMAT_MOD_X_TILED ||
+		    modifier == I915_FORMAT_MOD_Y_TILED)
+			return true;
+		fallthrough;
+	default:
+		return false;
+	}
+}
+
+static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
+					enum plane_id plane_id)
+{
+	/* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
+	if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
+	    IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0))
+		return false;
+
+	return plane_id < PLANE_SPRITE4;
+}
+
+static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
+					     u32 format, u64 modifier)
+{
+	struct drm_i915_private *dev_priv = to_i915(_plane->dev);
+	struct intel_plane *plane = to_intel_plane(_plane);
+
+	switch (modifier) {
+	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
+		if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
+			return false;
+		fallthrough;
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+	case I915_FORMAT_MOD_Y_TILED:
+	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
+		break;
+	default:
+		return false;
+	}
+
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+		if (is_ccs_modifier(modifier))
+			return true;
+		fallthrough;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_XYUV8888:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+		if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
+			return true;
+		fallthrough;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_XVYU2101010:
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_XBGR16161616F:
+	case DRM_FORMAT_ABGR16161616F:
+	case DRM_FORMAT_XRGB16161616F:
+	case DRM_FORMAT_ARGB16161616F:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
+	case DRM_FORMAT_XVYU12_16161616:
+	case DRM_FORMAT_XVYU16161616:
+		if (modifier == DRM_FORMAT_MOD_LINEAR ||
+		    modifier == I915_FORMAT_MOD_X_TILED ||
+		    modifier == I915_FORMAT_MOD_Y_TILED)
+			return true;
+		fallthrough;
+	default:
+		return false;
+	}
+}
+
+static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
+					    enum plane_id plane_id)
+{
+	if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
+		return gen12_plane_format_modifiers_mc_ccs;
+	else
+		return gen12_plane_format_modifiers_rc_ccs;
+}
+
+static const struct drm_plane_funcs skl_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = intel_plane_destroy,
+	.atomic_duplicate_state = intel_plane_duplicate_state,
+	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = skl_plane_format_mod_supported,
+};
+
+static const struct drm_plane_funcs gen12_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = intel_plane_destroy,
+	.atomic_duplicate_state = intel_plane_duplicate_state,
+	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = gen12_plane_format_mod_supported,
+};
+
+struct intel_plane *
+skl_universal_plane_create(struct drm_i915_private *dev_priv,
+			   enum pipe pipe, enum plane_id plane_id)
+{
+	const struct drm_plane_funcs *plane_funcs;
+	struct intel_plane *plane;
+	enum drm_plane_type plane_type;
+	unsigned int supported_rotations;
+	unsigned int supported_csc;
+	const u64 *modifiers;
+	const u32 *formats;
+	int num_formats;
+	int ret;
+
+	plane = intel_plane_alloc();
+	if (IS_ERR(plane))
+		return plane;
+
+	plane->pipe = pipe;
+	plane->id = plane_id;
+	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
+
+	plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
+	if (plane->has_fbc) {
+		struct intel_fbc *fbc = &dev_priv->fbc;
+
+		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 11) {
+		plane->min_width = icl_plane_min_width;
+		plane->max_width = icl_plane_max_width;
+		plane->max_height = icl_plane_max_height;
+	} else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
+		plane->max_width = glk_plane_max_width;
+		plane->max_height = skl_plane_max_height;
+	} else {
+		plane->max_width = skl_plane_max_width;
+		plane->max_height = skl_plane_max_height;
+	}
+
+	plane->max_stride = skl_plane_max_stride;
+	plane->update_plane = skl_update_plane;
+	plane->disable_plane = skl_disable_plane;
+	plane->get_hw_state = skl_plane_get_hw_state;
+	plane->check_plane = skl_plane_check;
+	plane->min_cdclk = skl_plane_min_cdclk;
+	plane->async_flip = skl_plane_async_flip;
+
+	if (INTEL_GEN(dev_priv) >= 11)
+		formats = icl_get_plane_formats(dev_priv, pipe,
+						plane_id, &num_formats);
+	else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+		formats = glk_get_plane_formats(dev_priv, pipe,
+						plane_id, &num_formats);
+	else
+		formats = skl_get_plane_formats(dev_priv, pipe,
+						plane_id, &num_formats);
+
+	plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
+	if (INTEL_GEN(dev_priv) >= 12) {
+		modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
+		plane_funcs = &gen12_plane_funcs;
+	} else {
+		if (plane->has_ccs)
+			modifiers = skl_plane_format_modifiers_ccs;
+		else
+			modifiers = skl_plane_format_modifiers_noccs;
+		plane_funcs = &skl_plane_funcs;
+	}
+
+	if (plane_id == PLANE_PRIMARY)
+		plane_type = DRM_PLANE_TYPE_PRIMARY;
+	else
+		plane_type = DRM_PLANE_TYPE_OVERLAY;
+
+	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
+				       0, plane_funcs,
+				       formats, num_formats, modifiers,
+				       plane_type,
+				       "plane %d%c", plane_id + 1,
+				       pipe_name(pipe));
+	if (ret)
+		goto fail;
+
+	supported_rotations =
+		DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
+		DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
+
+	if (INTEL_GEN(dev_priv) >= 10)
+		supported_rotations |= DRM_MODE_REFLECT_X;
+ 
+ 	drm_plane_create_rotation_property(&plane->base,
+					   DRM_MODE_ROTATE_0,
+					   supported_rotations);
+
+	supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
+
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+		supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
+
+	drm_plane_create_color_properties(&plane->base,
+					  supported_csc,
+					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  DRM_COLOR_YCBCR_BT709,
+					  DRM_COLOR_YCBCR_LIMITED_RANGE);
+
+	drm_plane_create_alpha_property(&plane->base);
+	drm_plane_create_blend_mode_property(&plane->base,
+					     BIT(DRM_MODE_BLEND_PIXEL_NONE) |
+					     BIT(DRM_MODE_BLEND_PREMULTI) |
+					     BIT(DRM_MODE_BLEND_COVERAGE));
+
+	drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
+
+	if (INTEL_GEN(dev_priv) >= 12)
+		drm_plane_enable_fb_damage_clips(&plane->base);
+
+	if (INTEL_GEN(dev_priv) >= 10)
+		drm_plane_create_scaling_filter_property(&plane->base,
+						BIT(DRM_SCALING_FILTER_DEFAULT) |
+						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
+
+	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+
+	return plane;
+
+fail:
+	intel_plane_free(plane);
+
+	return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index b7e208816074..ab2cd4825e2e 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -364,599 +364,6 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
 	return 0;
 }
 
-static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
-{
-	if (IS_ROCKETLAKE(i915))
-		return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
-	else
-		return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
-}
-
-bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
-			 enum plane_id plane_id)
-{
-	return INTEL_GEN(dev_priv) >= 11 &&
-		icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
-}
-
-bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
-{
-	return INTEL_GEN(dev_priv) >= 11 &&
-		icl_hdr_plane_mask() & BIT(plane_id);
-}
-
-static void
-skl_plane_ratio(const struct intel_crtc_state *crtc_state,
-		const struct intel_plane_state *plane_state,
-		unsigned int *num, unsigned int *den)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-
-	if (fb->format->cpp[0] == 8) {
-		if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
-			*num = 10;
-			*den = 8;
-		} else {
-			*num = 9;
-			*den = 8;
-		}
-	} else {
-		*num = 1;
-		*den = 1;
-	}
-}
-
-static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
-			       const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
-	unsigned int num, den;
-	unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
-
-	skl_plane_ratio(crtc_state, plane_state, &num, &den);
-
-	/* two pixels per clock on glk+ */
-	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
-		den *= 2;
-
-	return DIV_ROUND_UP(pixel_rate * num, den);
-}
-
-static int skl_plane_max_width(const struct drm_framebuffer *fb,
-			       int color_plane,
-			       unsigned int rotation)
-{
-	int cpp = fb->format->cpp[color_plane];
-
-	switch (fb->modifier) {
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-		/*
-		 * Validated limit is 4k, but has 5k should
-		 * work apart from the following features:
-		 * - Ytile (already limited to 4k)
-		 * - FP16 (already limited to 4k)
-		 * - render compression (already limited to 4k)
-		 * - KVMR sprite and cursor (don't care)
-		 * - horizontal panning (TODO verify this)
-		 * - pipe and plane scaling (TODO verify this)
-		 */
-		if (cpp == 8)
-			return 4096;
-		else
-			return 5120;
-	case I915_FORMAT_MOD_Y_TILED_CCS:
-	case I915_FORMAT_MOD_Yf_TILED_CCS:
-	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
-		/* FIXME AUX plane? */
-	case I915_FORMAT_MOD_Y_TILED:
-	case I915_FORMAT_MOD_Yf_TILED:
-		if (cpp == 8)
-			return 2048;
-		else
-			return 4096;
-	default:
-		MISSING_CASE(fb->modifier);
-		return 2048;
-	}
-}
-
-static int glk_plane_max_width(const struct drm_framebuffer *fb,
-			       int color_plane,
-			       unsigned int rotation)
-{
-	int cpp = fb->format->cpp[color_plane];
-
-	switch (fb->modifier) {
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-		if (cpp == 8)
-			return 4096;
-		else
-			return 5120;
-	case I915_FORMAT_MOD_Y_TILED_CCS:
-	case I915_FORMAT_MOD_Yf_TILED_CCS:
-		/* FIXME AUX plane? */
-	case I915_FORMAT_MOD_Y_TILED:
-	case I915_FORMAT_MOD_Yf_TILED:
-		if (cpp == 8)
-			return 2048;
-		else
-			return 5120;
-	default:
-		MISSING_CASE(fb->modifier);
-		return 2048;
-	}
-}
-
-static int icl_plane_min_width(const struct drm_framebuffer *fb,
-			       int color_plane,
-			       unsigned int rotation)
-{
-	/* Wa_14011264657, Wa_14011050563: gen11+ */
-	switch (fb->format->format) {
-	case DRM_FORMAT_C8:
-		return 18;
-	case DRM_FORMAT_RGB565:
-		return 10;
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_XVYU2101010:
-	case DRM_FORMAT_Y212:
-	case DRM_FORMAT_Y216:
-		return 6;
-	case DRM_FORMAT_NV12:
-		return 20;
-	case DRM_FORMAT_P010:
-	case DRM_FORMAT_P012:
-	case DRM_FORMAT_P016:
-		return 12;
-	case DRM_FORMAT_XRGB16161616F:
-	case DRM_FORMAT_XBGR16161616F:
-	case DRM_FORMAT_ARGB16161616F:
-	case DRM_FORMAT_ABGR16161616F:
-	case DRM_FORMAT_XVYU12_16161616:
-	case DRM_FORMAT_XVYU16161616:
-		return 4;
-	default:
-		return 1;
-	}
-}
-
-static int icl_plane_max_width(const struct drm_framebuffer *fb,
-			       int color_plane,
-			       unsigned int rotation)
-{
-	return 5120;
-}
-
-static int skl_plane_max_height(const struct drm_framebuffer *fb,
-				int color_plane,
-				unsigned int rotation)
-{
-	return 4096;
-}
-
-static int icl_plane_max_height(const struct drm_framebuffer *fb,
-				int color_plane,
-				unsigned int rotation)
-{
-	return 4320;
-}
-
-static unsigned int
-skl_plane_max_stride(struct intel_plane *plane,
-		     u32 pixel_format, u64 modifier,
-		     unsigned int rotation)
-{
-	const struct drm_format_info *info = drm_format_info(pixel_format);
-	int cpp = info->cpp[0];
-
-	/*
-	 * "The stride in bytes must not exceed the
-	 * of the size of 8K pixels and 32K bytes."
-	 */
-	if (drm_rotation_90_or_270(rotation))
-		return min(8192, 32768 / cpp);
-	else
-		return min(8192 * cpp, 32768);
-}
-
-static void
-skl_program_scaler(struct intel_plane *plane,
-		   const struct intel_crtc_state *crtc_state,
-		   const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	enum pipe pipe = plane->pipe;
-	int scaler_id = plane_state->scaler_id;
-	const struct intel_scaler *scaler =
-		&crtc_state->scaler_state.scalers[scaler_id];
-	int crtc_x = plane_state->uapi.dst.x1;
-	int crtc_y = plane_state->uapi.dst.y1;
-	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
-	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
-	u16 y_hphase, uv_rgb_hphase;
-	u16 y_vphase, uv_rgb_vphase;
-	int hscale, vscale;
-	u32 ps_ctrl;
-
-	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
-				      &plane_state->uapi.dst,
-				      0, INT_MAX);
-	vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
-				      &plane_state->uapi.dst,
-				      0, INT_MAX);
-
-	/* TODO: handle sub-pixel coordinates */
-	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
-	    !icl_is_hdr_plane(dev_priv, plane->id)) {
-		y_hphase = skl_scaler_calc_phase(1, hscale, false);
-		y_vphase = skl_scaler_calc_phase(1, vscale, false);
-
-		/* MPEG2 chroma siting convention */
-		uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
-		uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
-	} else {
-		/* not used */
-		y_hphase = 0;
-		y_vphase = 0;
-
-		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
-		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
-	}
-
-	ps_ctrl = skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0);
-	ps_ctrl |= PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode;
-
-	skl_scaler_setup_filter(dev_priv, pipe, scaler_id, 0,
-				plane_state->hw.scaling_filter);
-
-	intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
-	intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, scaler_id),
-			  PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
-	intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id),
-			  PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
-	intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, scaler_id),
-			  (crtc_x << 16) | crtc_y);
-	intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, scaler_id),
-			  (crtc_w << 16) | crtc_h);
-}
-
-/* Preoffset values for YUV to RGB Conversion */
-#define PREOFF_YUV_TO_RGB_HI		0x1800
-#define PREOFF_YUV_TO_RGB_ME		0x1F00
-#define PREOFF_YUV_TO_RGB_LO		0x1800
-
-#define  ROFF(x)          (((x) & 0xffff) << 16)
-#define  GOFF(x)          (((x) & 0xffff) << 0)
-#define  BOFF(x)          (((x) & 0xffff) << 16)
-
-static void
-icl_program_input_csc(struct intel_plane *plane,
-		      const struct intel_crtc_state *crtc_state,
-		      const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum pipe pipe = plane->pipe;
-	enum plane_id plane_id = plane->id;
-
-	static const u16 input_csc_matrix[][9] = {
-		/*
-		 * BT.601 full range YCbCr -> full range RGB
-		 * The matrix required is :
-		 * [1.000, 0.000, 1.371,
-		 *  1.000, -0.336, -0.698,
-		 *  1.000, 1.732, 0.0000]
-		 */
-		[DRM_COLOR_YCBCR_BT601] = {
-			0x7AF8, 0x7800, 0x0,
-			0x8B28, 0x7800, 0x9AC0,
-			0x0, 0x7800, 0x7DD8,
-		},
-		/*
-		 * BT.709 full range YCbCr -> full range RGB
-		 * The matrix required is :
-		 * [1.000, 0.000, 1.574,
-		 *  1.000, -0.187, -0.468,
-		 *  1.000, 1.855, 0.0000]
-		 */
-		[DRM_COLOR_YCBCR_BT709] = {
-			0x7C98, 0x7800, 0x0,
-			0x9EF8, 0x7800, 0xAC00,
-			0x0, 0x7800,  0x7ED8,
-		},
-		/*
-		 * BT.2020 full range YCbCr -> full range RGB
-		 * The matrix required is :
-		 * [1.000, 0.000, 1.474,
-		 *  1.000, -0.1645, -0.5713,
-		 *  1.000, 1.8814, 0.0000]
-		 */
-		[DRM_COLOR_YCBCR_BT2020] = {
-			0x7BC8, 0x7800, 0x0,
-			0x8928, 0x7800, 0xAA88,
-			0x0, 0x7800, 0x7F10,
-		},
-	};
-
-	/* Matrix for Limited Range to Full Range Conversion */
-	static const u16 input_csc_matrix_lr[][9] = {
-		/*
-		 * BT.601 Limted range YCbCr -> full range RGB
-		 * The matrix required is :
-		 * [1.164384, 0.000, 1.596027,
-		 *  1.164384, -0.39175, -0.812813,
-		 *  1.164384, 2.017232, 0.0000]
-		 */
-		[DRM_COLOR_YCBCR_BT601] = {
-			0x7CC8, 0x7950, 0x0,
-			0x8D00, 0x7950, 0x9C88,
-			0x0, 0x7950, 0x6810,
-		},
-		/*
-		 * BT.709 Limited range YCbCr -> full range RGB
-		 * The matrix required is :
-		 * [1.164384, 0.000, 1.792741,
-		 *  1.164384, -0.213249, -0.532909,
-		 *  1.164384, 2.112402, 0.0000]
-		 */
-		[DRM_COLOR_YCBCR_BT709] = {
-			0x7E58, 0x7950, 0x0,
-			0x8888, 0x7950, 0xADA8,
-			0x0, 0x7950,  0x6870,
-		},
-		/*
-		 * BT.2020 Limited range YCbCr -> full range RGB
-		 * The matrix required is :
-		 * [1.164, 0.000, 1.678,
-		 *  1.164, -0.1873, -0.6504,
-		 *  1.164, 2.1417, 0.0000]
-		 */
-		[DRM_COLOR_YCBCR_BT2020] = {
-			0x7D70, 0x7950, 0x0,
-			0x8A68, 0x7950, 0xAC00,
-			0x0, 0x7950, 0x6890,
-		},
-	};
-	const u16 *csc;
-
-	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
-		csc = input_csc_matrix[plane_state->hw.color_encoding];
-	else
-		csc = input_csc_matrix_lr[plane_state->hw.color_encoding];
-
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
-			  ROFF(csc[0]) | GOFF(csc[1]));
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
-			  BOFF(csc[2]));
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
-			  ROFF(csc[3]) | GOFF(csc[4]));
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
-			  BOFF(csc[5]));
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
-			  ROFF(csc[6]) | GOFF(csc[7]));
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
-			  BOFF(csc[8]));
-
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
-			  PREOFF_YUV_TO_RGB_HI);
-	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
-		intel_de_write_fw(dev_priv,
-				  PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
-				  0);
-	else
-		intel_de_write_fw(dev_priv,
-				  PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
-				  PREOFF_YUV_TO_RGB_ME);
-	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
-			  PREOFF_YUV_TO_RGB_LO);
-	intel_de_write_fw(dev_priv,
-			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
-	intel_de_write_fw(dev_priv,
-			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
-	intel_de_write_fw(dev_priv,
-			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
-}
-
-static void
-skl_plane_async_flip(struct intel_plane *plane,
-		     const struct intel_crtc_state *crtc_state,
-		     const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	unsigned long irqflags;
-	enum plane_id plane_id = plane->id;
-	enum pipe pipe = plane->pipe;
-	u32 surf_addr = plane_state->color_plane[0].offset;
-	u32 plane_ctl = plane_state->ctl;
-
-	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
-	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
-			  intel_plane_ggtt_offset(plane_state) + surf_addr);
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static void
-skl_program_plane(struct intel_plane *plane,
-		  const struct intel_crtc_state *crtc_state,
-		  const struct intel_plane_state *plane_state,
-		  int color_plane)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum plane_id plane_id = plane->id;
-	enum pipe pipe = plane->pipe;
-	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
-	u32 surf_addr = plane_state->color_plane[color_plane].offset;
-	u32 stride = skl_plane_stride(plane_state, color_plane);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	int aux_plane = intel_main_to_aux_plane(fb, color_plane);
-	int crtc_x = plane_state->uapi.dst.x1;
-	int crtc_y = plane_state->uapi.dst.y1;
-	u32 x = plane_state->color_plane[color_plane].x;
-	u32 y = plane_state->color_plane[color_plane].y;
-	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
-	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
-	u8 alpha = plane_state->hw.alpha >> 8;
-	u32 plane_color_ctl = 0, aux_dist = 0;
-	unsigned long irqflags;
-	u32 keymsk, keymax;
-	u32 plane_ctl = plane_state->ctl;
-
-	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
-
-	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
-		plane_color_ctl = plane_state->color_ctl |
-			glk_plane_color_ctl_crtc(crtc_state);
-
-	/* Sizes are 0 based */
-	src_w--;
-	src_h--;
-
-	keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
-
-	keymsk = key->channel_mask & 0x7ffffff;
-	if (alpha < 0xff)
-		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
-
-	/* The scaler will handle the output position */
-	if (plane_state->scaler_id >= 0) {
-		crtc_x = 0;
-		crtc_y = 0;
-	}
-
-	if (aux_plane) {
-		aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
-
-		if (INTEL_GEN(dev_priv) < 12)
-			aux_dist |= skl_plane_stride(plane_state, aux_plane);
-	}
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
-	intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
-			  (crtc_y << 16) | crtc_x);
-	intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
-			  (src_h << 16) | src_w);
-
-	intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
-
-	if (icl_is_hdr_plane(dev_priv, plane_id))
-		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
-				  plane_state->cus_ctl);
-
-	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
-		intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
-				  plane_color_ctl);
-
-	if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
-		icl_program_input_csc(plane, crtc_state, plane_state);
-
-	skl_write_plane_wm(plane, crtc_state);
-
-	intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
-			  key->min_value);
-	intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
-	intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
-
-	intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
-			  (y << 16) | x);
-
-	if (INTEL_GEN(dev_priv) < 11)
-		intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
-				  (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);
-
-	if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
-		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
-
-	/*
-	 * The control register self-arms if the plane was previously
-	 * disabled. Try to make the plane enable atomic by writing
-	 * the control register just before the surface register.
-	 */
-	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
-	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
-			  intel_plane_ggtt_offset(plane_state) + surf_addr);
-
-	if (plane_state->scaler_id >= 0)
-		skl_program_scaler(plane, crtc_state, plane_state);
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static void
-skl_update_plane(struct intel_plane *plane,
-		 const struct intel_crtc_state *crtc_state,
-		 const struct intel_plane_state *plane_state)
-{
-	int color_plane = 0;
-
-	if (plane_state->planar_linked_plane && !plane_state->planar_slave)
-		/* Program the UV plane on planar master */
-		color_plane = 1;
-
-	skl_program_plane(plane, crtc_state, plane_state, color_plane);
-}
-static void
-skl_disable_plane(struct intel_plane *plane,
-		  const struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum plane_id plane_id = plane->id;
-	enum pipe pipe = plane->pipe;
-	unsigned long irqflags;
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	if (icl_is_hdr_plane(dev_priv, plane_id))
-		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
-
-	skl_write_plane_wm(plane, crtc_state);
-
-	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
-	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static bool
-skl_plane_get_hw_state(struct intel_plane *plane,
-		       enum pipe *pipe)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum intel_display_power_domain power_domain;
-	enum plane_id plane_id = plane->id;
-	intel_wakeref_t wakeref;
-	bool ret;
-
-	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
-	if (!wakeref)
-		return false;
-
-	ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
-
-	*pipe = plane->pipe;
-
-	intel_display_power_put(dev_priv, power_domain, wakeref);
-
-	return ret;
-}
-
 static void i9xx_plane_linear_gamma(u16 gamma[8])
 {
 	/* The points are not evenly spaced. */
@@ -2281,239 +1688,6 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
 	return 0;
 }
 
-static bool intel_format_is_p01x(u32 format)
-{
-	switch (format) {
-	case DRM_FORMAT_P010:
-	case DRM_FORMAT_P012:
-	case DRM_FORMAT_P016:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
-			      const struct intel_plane_state *plane_state)
-{
-	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	unsigned int rotation = plane_state->hw.rotation;
-	struct drm_format_name_buf format_name;
-
-	if (!fb)
-		return 0;
-
-	if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
-	    is_ccs_modifier(fb->modifier)) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "RC support only with 0/180 degree rotation (%x)\n",
-			    rotation);
-		return -EINVAL;
-	}
-
-	if (rotation & DRM_MODE_REFLECT_X &&
-	    fb->modifier == DRM_FORMAT_MOD_LINEAR) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "horizontal flip is not supported with linear surface formats\n");
-		return -EINVAL;
-	}
-
-	if (drm_rotation_90_or_270(rotation)) {
-		if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
-		    fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
-			drm_dbg_kms(&dev_priv->drm,
-				    "Y/Yf tiling required for 90/270!\n");
-			return -EINVAL;
-		}
-
-		/*
-		 * 90/270 is not allowed with RGB64 16:16:16:16 and
-		 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
-		 */
-		switch (fb->format->format) {
-		case DRM_FORMAT_RGB565:
-			if (INTEL_GEN(dev_priv) >= 11)
-				break;
-			fallthrough;
-		case DRM_FORMAT_C8:
-		case DRM_FORMAT_XRGB16161616F:
-		case DRM_FORMAT_XBGR16161616F:
-		case DRM_FORMAT_ARGB16161616F:
-		case DRM_FORMAT_ABGR16161616F:
-		case DRM_FORMAT_Y210:
-		case DRM_FORMAT_Y212:
-		case DRM_FORMAT_Y216:
-		case DRM_FORMAT_XVYU12_16161616:
-		case DRM_FORMAT_XVYU16161616:
-			drm_dbg_kms(&dev_priv->drm,
-				    "Unsupported pixel format %s for 90/270!\n",
-				    drm_get_format_name(fb->format->format,
-							&format_name));
-			return -EINVAL;
-		default:
-			break;
-		}
-	}
-
-	/* Y-tiling is not supported in IF-ID Interlace mode */
-	if (crtc_state->hw.enable &&
-	    crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
-	    (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
-	     fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
-	     fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
-	     fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
-	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
-	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "Y/Yf tiling not supported in IF-ID mode\n");
-		return -EINVAL;
-	}
-
-	/* Wa_1606054188:tgl */
-	if (IS_TIGERLAKE(dev_priv) &&
-	    plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
-	    intel_format_is_p01x(fb->format->format)) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "Source color keying not supported with P01x formats\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
-					   const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv =
-		to_i915(plane_state->uapi.plane->dev);
-	int crtc_x = plane_state->uapi.dst.x1;
-	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
-	int pipe_src_w = crtc_state->pipe_src_w;
-
-	/*
-	 * Display WA #1175: cnl,glk
-	 * Planes other than the cursor may cause FIFO underflow and display
-	 * corruption if starting less than 4 pixels from the right edge of
-	 * the screen.
-	 * Besides the above WA fix the similar problem, where planes other
-	 * than the cursor ending less than 4 pixels from the left edge of the
-	 * screen may cause FIFO underflow and display corruption.
-	 */
-	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
-	    (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "requested plane X %s position %d invalid (valid range %d-%d)\n",
-			    crtc_x + crtc_w < 4 ? "end" : "start",
-			    crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
-			    4, pipe_src_w - 4);
-		return -ERANGE;
-	}
-
-	return 0;
-}
-
-static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
-{
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	unsigned int rotation = plane_state->hw.rotation;
-	int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
-
-	/* Display WA #1106 */
-	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
-	    src_w & 3 &&
-	    (rotation == DRM_MODE_ROTATE_270 ||
-	     rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
-		DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
-			       const struct drm_framebuffer *fb)
-{
-	/*
-	 * We don't yet know the final source width nor
-	 * whether we can use the HQ scaler mode. Assume
-	 * the best case.
-	 * FIXME need to properly check this later.
-	 */
-	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
-	    !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
-		return 0x30000 - 1;
-	else
-		return 0x20000 - 1;
-}
-
-static int skl_plane_check(struct intel_crtc_state *crtc_state,
-			   struct intel_plane_state *plane_state)
-{
-	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
-	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
-	int ret;
-
-	ret = skl_plane_check_fb(crtc_state, plane_state);
-	if (ret)
-		return ret;
-
-	/* use scaler when colorkey is not required */
-	if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
-		min_scale = 1;
-		max_scale = skl_plane_max_scale(dev_priv, fb);
-	}
-
-	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
-						min_scale, max_scale, true);
-	if (ret)
-		return ret;
-
-	ret = skl_check_plane_surface(plane_state);
-	if (ret)
-		return ret;
-
-	if (!plane_state->uapi.visible)
-		return 0;
-
-	ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
-	if (ret)
-		return ret;
-
-	ret = intel_plane_check_src_coordinates(plane_state);
-	if (ret)
-		return ret;
-
-	ret = skl_plane_check_nv12_rotation(plane_state);
-	if (ret)
-		return ret;
-
-	/* HW only has 8 bits pixel precision, disable plane if invisible */
-	if (!(plane_state->hw.alpha >> 8))
-		plane_state->uapi.visible = false;
-
-	plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
-
-	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
-		plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
-							     plane_state);
-
-	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
-	    icl_is_hdr_plane(dev_priv, plane->id))
-		/* Enable and use MPEG-2 chroma siting */
-		plane_state->cus_ctl = PLANE_CUS_ENABLE |
-			PLANE_CUS_HPHASE_0 |
-			PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
-	else
-		plane_state->cus_ctl = 0;
-
-	return 0;
-}
-
 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
 {
 	return INTEL_GEN(dev_priv) >= 9;
@@ -2640,169 +1814,41 @@ static const u32 g4x_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
-static const u64 i9xx_plane_format_modifiers[] = {
-	I915_FORMAT_MOD_X_TILED,
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
-};
-
-static const u32 snb_plane_formats[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_XRGB16161616F,
-	DRM_FORMAT_XBGR16161616F,
-	DRM_FORMAT_YUYV,
-	DRM_FORMAT_YVYU,
-	DRM_FORMAT_UYVY,
-	DRM_FORMAT_VYUY,
-};
-
-static const u32 vlv_plane_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_ABGR2101010,
-	DRM_FORMAT_YUYV,
-	DRM_FORMAT_YVYU,
-	DRM_FORMAT_UYVY,
-	DRM_FORMAT_VYUY,
-};
-
-static const u32 chv_pipe_b_sprite_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_ARGB2101010,
-	DRM_FORMAT_ABGR2101010,
-	DRM_FORMAT_YUYV,
-	DRM_FORMAT_YVYU,
-	DRM_FORMAT_UYVY,
-	DRM_FORMAT_VYUY,
-};
-
-static const u32 skl_plane_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_XRGB16161616F,
-	DRM_FORMAT_XBGR16161616F,
-	DRM_FORMAT_YUYV,
-	DRM_FORMAT_YVYU,
-	DRM_FORMAT_UYVY,
-	DRM_FORMAT_VYUY,
-	DRM_FORMAT_XYUV8888,
-};
-
-static const u32 skl_planar_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_XRGB16161616F,
-	DRM_FORMAT_XBGR16161616F,
-	DRM_FORMAT_YUYV,
-	DRM_FORMAT_YVYU,
-	DRM_FORMAT_UYVY,
-	DRM_FORMAT_VYUY,
-	DRM_FORMAT_NV12,
-	DRM_FORMAT_XYUV8888,
-};
-
-static const u32 glk_planar_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_XRGB16161616F,
-	DRM_FORMAT_XBGR16161616F,
-	DRM_FORMAT_YUYV,
-	DRM_FORMAT_YVYU,
-	DRM_FORMAT_UYVY,
-	DRM_FORMAT_VYUY,
-	DRM_FORMAT_NV12,
-	DRM_FORMAT_XYUV8888,
-	DRM_FORMAT_P010,
-	DRM_FORMAT_P012,
-	DRM_FORMAT_P016,
-};
-
-static const u32 icl_sdr_y_plane_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
+static const u64 i9xx_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static const u32 snb_plane_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
 	DRM_FORMAT_XRGB2101010,
 	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_ARGB2101010,
-	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_XRGB16161616F,
+	DRM_FORMAT_XBGR16161616F,
 	DRM_FORMAT_YUYV,
 	DRM_FORMAT_YVYU,
 	DRM_FORMAT_UYVY,
 	DRM_FORMAT_VYUY,
-	DRM_FORMAT_Y210,
-	DRM_FORMAT_Y212,
-	DRM_FORMAT_Y216,
-	DRM_FORMAT_XYUV8888,
-	DRM_FORMAT_XVYU2101010,
-	DRM_FORMAT_XVYU12_16161616,
-	DRM_FORMAT_XVYU16161616,
 };
 
-static const u32 icl_sdr_uv_plane_formats[] = {
+static const u32 vlv_plane_formats[] = {
 	DRM_FORMAT_C8,
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XRGB2101010,
 	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_ARGB2101010,
 	DRM_FORMAT_ABGR2101010,
 	DRM_FORMAT_YUYV,
 	DRM_FORMAT_YVYU,
 	DRM_FORMAT_UYVY,
 	DRM_FORMAT_VYUY,
-	DRM_FORMAT_NV12,
-	DRM_FORMAT_P010,
-	DRM_FORMAT_P012,
-	DRM_FORMAT_P016,
-	DRM_FORMAT_Y210,
-	DRM_FORMAT_Y212,
-	DRM_FORMAT_Y216,
-	DRM_FORMAT_XYUV8888,
-	DRM_FORMAT_XVYU2101010,
-	DRM_FORMAT_XVYU12_16161616,
-	DRM_FORMAT_XVYU16161616,
 };
 
-static const u32 icl_hdr_plane_formats[] = {
+static const u32 chv_pipe_b_sprite_formats[] = {
 	DRM_FORMAT_C8,
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_XRGB8888,
@@ -2813,60 +1859,10 @@ static const u32 icl_hdr_plane_formats[] = {
 	DRM_FORMAT_XBGR2101010,
 	DRM_FORMAT_ARGB2101010,
 	DRM_FORMAT_ABGR2101010,
-	DRM_FORMAT_XRGB16161616F,
-	DRM_FORMAT_XBGR16161616F,
-	DRM_FORMAT_ARGB16161616F,
-	DRM_FORMAT_ABGR16161616F,
 	DRM_FORMAT_YUYV,
 	DRM_FORMAT_YVYU,
 	DRM_FORMAT_UYVY,
 	DRM_FORMAT_VYUY,
-	DRM_FORMAT_NV12,
-	DRM_FORMAT_P010,
-	DRM_FORMAT_P012,
-	DRM_FORMAT_P016,
-	DRM_FORMAT_Y210,
-	DRM_FORMAT_Y212,
-	DRM_FORMAT_Y216,
-	DRM_FORMAT_XYUV8888,
-	DRM_FORMAT_XVYU2101010,
-	DRM_FORMAT_XVYU12_16161616,
-	DRM_FORMAT_XVYU16161616,
-};
-
-static const u64 skl_plane_format_modifiers_noccs[] = {
-	I915_FORMAT_MOD_Yf_TILED,
-	I915_FORMAT_MOD_Y_TILED,
-	I915_FORMAT_MOD_X_TILED,
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
-};
-
-static const u64 skl_plane_format_modifiers_ccs[] = {
-	I915_FORMAT_MOD_Yf_TILED_CCS,
-	I915_FORMAT_MOD_Y_TILED_CCS,
-	I915_FORMAT_MOD_Yf_TILED,
-	I915_FORMAT_MOD_Y_TILED,
-	I915_FORMAT_MOD_X_TILED,
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
-};
-
-static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
-	I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
-	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
-	I915_FORMAT_MOD_Y_TILED,
-	I915_FORMAT_MOD_X_TILED,
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
-};
-
-static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
-	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
-	I915_FORMAT_MOD_Y_TILED,
-	I915_FORMAT_MOD_X_TILED,
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
 };
 
 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
@@ -2961,148 +1957,6 @@ static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
 	}
 }
 
-static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
-					   u32 format, u64 modifier)
-{
-	struct intel_plane *plane = to_intel_plane(_plane);
-
-	switch (modifier) {
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-	case I915_FORMAT_MOD_Y_TILED:
-	case I915_FORMAT_MOD_Yf_TILED:
-		break;
-	case I915_FORMAT_MOD_Y_TILED_CCS:
-	case I915_FORMAT_MOD_Yf_TILED_CCS:
-		if (!plane->has_ccs)
-			return false;
-		break;
-	default:
-		return false;
-	}
-
-	switch (format) {
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-		if (is_ccs_modifier(modifier))
-			return true;
-		fallthrough;
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_XYUV8888:
-	case DRM_FORMAT_P010:
-	case DRM_FORMAT_P012:
-	case DRM_FORMAT_P016:
-	case DRM_FORMAT_XVYU2101010:
-		if (modifier == I915_FORMAT_MOD_Yf_TILED)
-			return true;
-		fallthrough;
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_XBGR16161616F:
-	case DRM_FORMAT_ABGR16161616F:
-	case DRM_FORMAT_XRGB16161616F:
-	case DRM_FORMAT_ARGB16161616F:
-	case DRM_FORMAT_Y210:
-	case DRM_FORMAT_Y212:
-	case DRM_FORMAT_Y216:
-	case DRM_FORMAT_XVYU12_16161616:
-	case DRM_FORMAT_XVYU16161616:
-		if (modifier == DRM_FORMAT_MOD_LINEAR ||
-		    modifier == I915_FORMAT_MOD_X_TILED ||
-		    modifier == I915_FORMAT_MOD_Y_TILED)
-			return true;
-		fallthrough;
-	default:
-		return false;
-	}
-}
-
-static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
-					enum plane_id plane_id)
-{
-	/* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
-	if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
-	    IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0))
-		return false;
-
-	return plane_id < PLANE_SPRITE4;
-}
-
-static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
-					     u32 format, u64 modifier)
-{
-	struct drm_i915_private *dev_priv = to_i915(_plane->dev);
-	struct intel_plane *plane = to_intel_plane(_plane);
-
-	switch (modifier) {
-	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
-		if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
-			return false;
-		fallthrough;
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-	case I915_FORMAT_MOD_Y_TILED:
-	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
-		break;
-	default:
-		return false;
-	}
-
-	switch (format) {
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-		if (is_ccs_modifier(modifier))
-			return true;
-		fallthrough;
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_XYUV8888:
-	case DRM_FORMAT_P010:
-	case DRM_FORMAT_P012:
-	case DRM_FORMAT_P016:
-		if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
-			return true;
-		fallthrough;
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_XVYU2101010:
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_XBGR16161616F:
-	case DRM_FORMAT_ABGR16161616F:
-	case DRM_FORMAT_XRGB16161616F:
-	case DRM_FORMAT_ARGB16161616F:
-	case DRM_FORMAT_Y210:
-	case DRM_FORMAT_Y212:
-	case DRM_FORMAT_Y216:
-	case DRM_FORMAT_XVYU12_16161616:
-	case DRM_FORMAT_XVYU16161616:
-		if (modifier == DRM_FORMAT_MOD_LINEAR ||
-		    modifier == I915_FORMAT_MOD_X_TILED ||
-		    modifier == I915_FORMAT_MOD_Y_TILED)
-			return true;
-		fallthrough;
-	default:
-		return false;
-	}
-}
 
 static const struct drm_plane_funcs g4x_sprite_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
@@ -3131,251 +1985,6 @@ static const struct drm_plane_funcs vlv_sprite_funcs = {
 	.format_mod_supported = vlv_sprite_format_mod_supported,
 };
 
-static const struct drm_plane_funcs skl_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = intel_plane_destroy,
-	.atomic_duplicate_state = intel_plane_duplicate_state,
-	.atomic_destroy_state = intel_plane_destroy_state,
-	.format_mod_supported = skl_plane_format_mod_supported,
-};
-
-static const struct drm_plane_funcs gen12_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = intel_plane_destroy,
-	.atomic_duplicate_state = intel_plane_duplicate_state,
-	.atomic_destroy_state = intel_plane_destroy_state,
-	.format_mod_supported = gen12_plane_format_mod_supported,
-};
-
-static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
-			      enum pipe pipe, enum plane_id plane_id)
-{
-	if (!HAS_FBC(dev_priv))
-		return false;
-
-	return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
-}
-
-static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
-				 enum pipe pipe, enum plane_id plane_id)
-{
-	/* Display WA #0870: skl, bxt */
-	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
-		return false;
-
-	if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
-		return false;
-
-	if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
-		return false;
-
-	return true;
-}
-
-static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
-					enum pipe pipe, enum plane_id plane_id,
-					int *num_formats)
-{
-	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
-		*num_formats = ARRAY_SIZE(skl_planar_formats);
-		return skl_planar_formats;
-	} else {
-		*num_formats = ARRAY_SIZE(skl_plane_formats);
-		return skl_plane_formats;
-	}
-}
-
-static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
-					enum pipe pipe, enum plane_id plane_id,
-					int *num_formats)
-{
-	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
-		*num_formats = ARRAY_SIZE(glk_planar_formats);
-		return glk_planar_formats;
-	} else {
-		*num_formats = ARRAY_SIZE(skl_plane_formats);
-		return skl_plane_formats;
-	}
-}
-
-static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
-					enum pipe pipe, enum plane_id plane_id,
-					int *num_formats)
-{
-	if (icl_is_hdr_plane(dev_priv, plane_id)) {
-		*num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
-		return icl_hdr_plane_formats;
-	} else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
-		*num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
-		return icl_sdr_y_plane_formats;
-	} else {
-		*num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
-		return icl_sdr_uv_plane_formats;
-	}
-}
-
-static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
-					    enum plane_id plane_id)
-{
-	if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
-		return gen12_plane_format_modifiers_mc_ccs;
-	else
-		return gen12_plane_format_modifiers_rc_ccs;
-}
-
-static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
-			      enum pipe pipe, enum plane_id plane_id)
-{
-	if (plane_id == PLANE_CURSOR)
-		return false;
-
-	if (INTEL_GEN(dev_priv) >= 10)
-		return true;
-
-	if (IS_GEMINILAKE(dev_priv))
-		return pipe != PIPE_C;
-
-	return pipe != PIPE_C &&
-		(plane_id == PLANE_PRIMARY ||
-		 plane_id == PLANE_SPRITE0);
-}
-
-struct intel_plane *
-skl_universal_plane_create(struct drm_i915_private *dev_priv,
-			   enum pipe pipe, enum plane_id plane_id)
-{
-	const struct drm_plane_funcs *plane_funcs;
-	struct intel_plane *plane;
-	enum drm_plane_type plane_type;
-	unsigned int supported_rotations;
-	unsigned int supported_csc;
-	const u64 *modifiers;
-	const u32 *formats;
-	int num_formats;
-	int ret;
-
-	plane = intel_plane_alloc();
-	if (IS_ERR(plane))
-		return plane;
-
-	plane->pipe = pipe;
-	plane->id = plane_id;
-	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
-
-	plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
-	if (plane->has_fbc) {
-		struct intel_fbc *fbc = &dev_priv->fbc;
-
-		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 11) {
-		plane->min_width = icl_plane_min_width;
-		plane->max_width = icl_plane_max_width;
-		plane->max_height = icl_plane_max_height;
-	} else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
-		plane->max_width = glk_plane_max_width;
-		plane->max_height = skl_plane_max_height;
-	} else {
-		plane->max_width = skl_plane_max_width;
-		plane->max_height = skl_plane_max_height;
-	}
-
-	plane->max_stride = skl_plane_max_stride;
-	plane->update_plane = skl_update_plane;
-	plane->disable_plane = skl_disable_plane;
-	plane->get_hw_state = skl_plane_get_hw_state;
-	plane->check_plane = skl_plane_check;
-	plane->min_cdclk = skl_plane_min_cdclk;
-	plane->async_flip = skl_plane_async_flip;
-
-	if (INTEL_GEN(dev_priv) >= 11)
-		formats = icl_get_plane_formats(dev_priv, pipe,
-						plane_id, &num_formats);
-	else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
-		formats = glk_get_plane_formats(dev_priv, pipe,
-						plane_id, &num_formats);
-	else
-		formats = skl_get_plane_formats(dev_priv, pipe,
-						plane_id, &num_formats);
-
-	plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
-	if (INTEL_GEN(dev_priv) >= 12) {
-		modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
-		plane_funcs = &gen12_plane_funcs;
-	} else {
-		if (plane->has_ccs)
-			modifiers = skl_plane_format_modifiers_ccs;
-		else
-			modifiers = skl_plane_format_modifiers_noccs;
-		plane_funcs = &skl_plane_funcs;
-	}
-
-	if (plane_id == PLANE_PRIMARY)
-		plane_type = DRM_PLANE_TYPE_PRIMARY;
-	else
-		plane_type = DRM_PLANE_TYPE_OVERLAY;
-
-	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
-				       0, plane_funcs,
-				       formats, num_formats, modifiers,
-				       plane_type,
-				       "plane %d%c", plane_id + 1,
-				       pipe_name(pipe));
-	if (ret)
-		goto fail;
-
-	supported_rotations =
-		DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
-		DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
-
-	if (INTEL_GEN(dev_priv) >= 10)
-		supported_rotations |= DRM_MODE_REFLECT_X;
-
-	drm_plane_create_rotation_property(&plane->base,
-					   DRM_MODE_ROTATE_0,
-					   supported_rotations);
-
-	supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
-
-	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
-		supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
-
-	drm_plane_create_color_properties(&plane->base,
-					  supported_csc,
-					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
-					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-					  DRM_COLOR_YCBCR_BT709,
-					  DRM_COLOR_YCBCR_LIMITED_RANGE);
-
-	drm_plane_create_alpha_property(&plane->base);
-	drm_plane_create_blend_mode_property(&plane->base,
-					     BIT(DRM_MODE_BLEND_PIXEL_NONE) |
-					     BIT(DRM_MODE_BLEND_PREMULTI) |
-					     BIT(DRM_MODE_BLEND_COVERAGE));
-
-	drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
-
-	if (INTEL_GEN(dev_priv) >= 12)
-		drm_plane_enable_fb_damage_clips(&plane->base);
-
-	if (INTEL_GEN(dev_priv) >= 10)
-		drm_plane_create_scaling_filter_property(&plane->base,
-						BIT(DRM_SCALING_FILTER_DEFAULT) |
-						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
-
-	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
-
-	return plane;
-
-fail:
-	intel_plane_free(plane);
-
-	return ERR_PTR(ret);
-}
-
 struct intel_plane *
 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, int sprite)
@@ -3388,10 +1997,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 	int num_formats;
 	int ret, zpos;
 
-	if (INTEL_GEN(dev_priv) >= 9)
-		return skl_universal_plane_create(dev_priv, pipe,
-						  PLANE_SPRITE0 + sprite);
-
 	plane = intel_plane_alloc();
 	if (IS_ERR(plane))
 		return plane;
-- 
2.27.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (8 preceding siblings ...)
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 9/9] drm/i915: migrate skl planes code " Dave Airlie
@ 2020-12-10  4:32 ` Patchwork
  2020-12-10  4:33 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2020-12-10  4:32 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
URL   : https://patchwork.freedesktop.org/series/84761/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
ee7dca5fec1e drm/i915/display: move needs_modeset to an inline in header
f7906d61c852 drm/i915/display: move to_intel_frontbuffer to header
89c17eeef1fa drm/i915/display: fix misused comma
e673ce40272b drm/i915: refactor cursor code out of i915_display.c
-:24: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#24: 
new file mode 100644

-:522: WARNING:UNSPECIFIED_INT: Prefer 'unsigned int' to bare use of 'unsigned'
#522: FILE: drivers/gpu/drm/i915/display/intel_cursor.c:494:
+		unsigned width = drm_rect_width(&plane_state->uapi.dst);

-:523: WARNING:UNSPECIFIED_INT: Prefer 'unsigned int' to bare use of 'unsigned'
#523: FILE: drivers/gpu/drm/i915/display/intel_cursor.c:495:
+		unsigned height = drm_rect_height(&plane_state->uapi.dst);

-:552: WARNING:REPEATED_WORD: Possible repeated word: 'by'
#552: FILE: drivers/gpu/drm/i915/display/intel_cursor.c:524:
+	 * The other registers are armed by by the CURBASE write

-:779: CHECK:SPACING: No space is necessary after a cast
#779: FILE: drivers/gpu/drm/i915/display/intel_cursor.c:751:
+	cursor->i9xx_plane = (enum i9xx_plane_id) pipe;

total: 0 errors, 4 warnings, 1 checks, 1680 lines checked
cda39caa4c68 drm/i915: refactor some crtc code out of intel display.
-:26: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#26: 
new file mode 100644

-:601: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#601: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:571:
+		return 32*1024;
 		         ^

-:604: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#604: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:574:
+			return 16*1024;
 			         ^

-:606: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#606: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:576:
+			return 32*1024;
 			         ^

-:609: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#609: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:579:
+			return 8*1024;
 			        ^

-:611: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#611: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:581:
+			return 16*1024;
 			         ^

-:614: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#614: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:584:
+			return 4*1024;
 			        ^

-:616: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#616: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:586:
+			return 8*1024;
 			        ^

-:663: CHECK:SPACING: No space is necessary after a cast
#663: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:633:
+		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;

-:665: CHECK:SPACING: No space is necessary after a cast
#665: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:635:
+		plane->i9xx_plane = (enum i9xx_plane_id) pipe;

-:952: WARNING:AVOID_BUG: Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()
#952: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:922:
+	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||

-:953: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "dev_priv->pipe_to_crtc_mapping[pipe]"
#953: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:923:
+	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL);

-:959: WARNING:AVOID_BUG: Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()
#959: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:929:
+		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||

-:960: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "dev_priv->plane_to_crtc_mapping[i9xx_plane]"
#960: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:930:
+		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);

-:966: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#966: FILE: drivers/gpu/drm/i915/display/intel_crtc.c:936:
+		drm_crtc_create_scaling_filter_property(&crtc->base,
+						BIT(DRM_SCALING_FILTER_DEFAULT) |

total: 0 errors, 3 warnings, 12 checks, 1969 lines checked
3a72e7ca995f drm/i915: refactor pll code out into intel_dpll_legacy.c
-:1574: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#1574: 
new file mode 100644

-:1594: CHECK:LOGICAL_CONTINUATIONS: Logical continuations should be on the previous line
#1594: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:16:
+	return dev_priv->vbt.lvds_use_ssc
+		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);

-:1607: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
#1607: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:29:
+};
+static const struct intel_limit intel_limits_i8xx_dac = {

-:1672: CHECK:LINE_SPACING: Please don't use multiple blank lines
#1672: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:94:
+
+

-:2244: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#2244: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:666:
+				for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {

-:2315: CHECK:SPACING: spaces preferred around that '/' (ctx:VxV)
#2315: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:737:
+			if (m2 > INT_MAX/clock.m1)
 			                ^

-:2412: CHECK:BRACES: braces {} should be used on all arms of this statement
#2412: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:834:
+	if (IS_PINEVIEW(dev_priv))
[...]
+	else {
[...]

-:2414: CHECK:BRACES: Unbalanced braces around else statement
#2414: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:836:
+	else {

-:2532: CHECK:LINE_SPACING: Please don't use multiple blank lines
#2532: FILE: drivers/gpu/drm/i915/display/intel_dpll_legacy.c:954:
+
+

total: 0 errors, 2 warnings, 7 checks, 2896 lines checked
3f29deb02bb0 drm/i915: split fdi code out from intel_display.c
-:785: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#785: 
new file mode 100644

-:880: WARNING:AVOID_BUG: Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()
#880: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:91:
+		BUG();

-:885: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#885: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:96:
+int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
+				  struct intel_crtc_state *pipe_config)

-:917: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#917: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:128:
+	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
 	                                               ^

-:918: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
#918: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:129:
+		pipe_config->pipe_bpp -= 2*3;
 		                          ^

-:967: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#967: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:178:
+	udelay(1000);

-:972: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#972: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:183:
+			       intel_de_read(dev_priv, reg) | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE);

-:989: WARNING:BLOCK_COMMENT_STYLE: Block comments use * on subsequent lines
#989: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:200:
+	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+	   for train result */

-:989: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#989: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:200:
+	   for train result */

-:996: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#996: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:207:
+	udelay(150);

-:1014: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1014: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:225:
+	udelay(150);

-:1050: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1050: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:261:
+	udelay(150);

-:1069: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#1069: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:280:
+
+}

-:1089: WARNING:BLOCK_COMMENT_STYLE: Block comments use * on subsequent lines
#1089: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:300:
+	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+	   for train result */

-:1089: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#1089: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:300:
+	   for train result */

-:1097: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1097: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:308:
+	udelay(150);

-:1126: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1126: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:337:
+	udelay(150);

-:1136: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1136: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:347:
+		udelay(500);

-:1149: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1149: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:360:
+			udelay(50);

-:1181: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1181: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:392:
+	udelay(150);

-:1191: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1191: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:402:
+		udelay(500);

-:1204: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1204: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:415:
+			udelay(50);

-:1226: WARNING:BLOCK_COMMENT_STYLE: Block comments use * on subsequent lines
#1226: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:437:
+	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+	   for train result */

-:1226: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#1226: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:437:
+	   for train result */

-:1234: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1234: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:445:
+	udelay(150);

-:1262: CHECK:SPACING: spaces preferred around that '/' (ctx:VxV)
#1262: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:473:
+		temp |= snb_b_fdi_train_param[j/2];
 		                               ^

-:1358: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1358: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:569:
+	udelay(200);

-:1365: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1365: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:576:
+	udelay(200);

-:1374: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1374: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:585:
+		udelay(100);

-:1397: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1397: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:608:
+	udelay(100);

-:1405: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1405: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:616:
+	udelay(100);

-:1428: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1428: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:639:
+	udelay(100);

-:1457: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#1457: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:668:
+	udelay(100);

total: 0 errors, 9 warnings, 24 checks, 1432 lines checked
8fd0727c2a20 drm/i915: migrate hsw fdi code to new file.
-:306: WARNING:LONG_LINE: line length of 123 exceeds 100 columns
#306: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:590:
+		       FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2) | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);

-:314: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#314: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:598:
+	udelay(220);

-:326: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#326: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:610:
+	 * testing each value twice. */

-:338: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#338: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:622:
+		 * port reversal bit */

-:340: WARNING:LONG_LINE: line length of 118 exceeds 100 columns
#340: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:624:
+			       DDI_BUF_CTL_ENABLE | ((crtc_state->fdi_lanes - 1) << 1) | DDI_BUF_TRANS_SELECT(i / 2));

-:343: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#343: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:627:
+		udelay(600);

-:354: CHECK:USLEEP_RANGE: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst
#354: FILE: drivers/gpu/drm/i915/display/intel_fdi.c:638:
+		udelay(30);

total: 0 errors, 4 warnings, 3 checks, 380 lines checked
6a72e6f85636 drm/i915: migrate skl planes code new file
-:64: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#64: 
new file mode 100644

-:264: CHECK:LINE_SPACING: Please don't use multiple blank lines
#264: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:196:
+
+

-:592: WARNING:TYPO_SPELLING: 'Limted' may be misspelled - perhaps 'Limited'?
#592: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:524:
+		 * BT.601 Limted range YCbCr -> full range RGB

-:779: WARNING:LONG_LINE: line length of 105 exceeds 100 columns
#779: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:711:
+				  (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);

-:812: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
#812: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:744:
+}
+static void

-:1141: WARNING:UNNECESSARY_ELSE: else is not generally useful after a break or return
#1141: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1073:
+		return skl_planar_formats;
+	} else {

-:1154: WARNING:UNNECESSARY_ELSE: else is not generally useful after a break or return
#1154: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1086:
+		return glk_planar_formats;
+	} else {

-:1170: WARNING:UNNECESSARY_ELSE: else is not generally useful after a break or return
#1170: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1102:
+		return icl_sdr_y_plane_formats;
+	} else {

-:1454: ERROR:TRAILING_WHITESPACE: trailing whitespace
#1454: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1386:
+ $

-:1454: WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1454: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1386:
+ $

-:1455: ERROR:CODE_INDENT: code indent should use tabs where possible
#1455: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1387:
+ ^Idrm_plane_create_rotation_property(&plane->base,$

-:1455: WARNING:SPACE_BEFORE_TAB: please, no space before tabs
#1455: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1387:
+ ^Idrm_plane_create_rotation_property(&plane->base,$

-:1455: WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1455: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1387:
+ ^Idrm_plane_create_rotation_property(&plane->base,$

-:1484: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1484: FILE: drivers/gpu/drm/i915/display/intel_gen9_plane.c:1416:
+		drm_plane_create_scaling_filter_property(&plane->base,
+						BIT(DRM_SCALING_FILTER_DEFAULT) |

total: 2 errors, 9 warnings, 3 checks, 2955 lines checked


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (9 preceding siblings ...)
  2020-12-10  4:32 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header Patchwork
@ 2020-12-10  4:33 ` Patchwork
  2020-12-10  4:37 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2020-12-10  4:33 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
URL   : https://patchwork.freedesktop.org/series/84761/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.
-
+drivers/gpu/drm/i915/gt/intel_reset.c:1310:5: warning: context imbalance in 'intel_gt_reset_trylock' - different lock contexts for basic block
+drivers/gpu/drm/i915/gt/selftest_reset.c:100:20:    expected void *in
+drivers/gpu/drm/i915/gt/selftest_reset.c:100:20:    got void [noderef] __iomem *[assigned] s
+drivers/gpu/drm/i915/gt/selftest_reset.c:100:20: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/i915/gt/selftest_reset.c:101:46:    expected void const *src
+drivers/gpu/drm/i915/gt/selftest_reset.c:101:46:    got void [noderef] __iomem *[assigned] s
+drivers/gpu/drm/i915/gt/selftest_reset.c:101:46: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/i915/gt/selftest_reset.c:136:20:    expected void *in
+drivers/gpu/drm/i915/gt/selftest_reset.c:136:20:    got void [noderef] __iomem *[assigned] s
+drivers/gpu/drm/i915/gt/selftest_reset.c:136:20: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/i915/gt/selftest_reset.c:137:46:    expected void const *src
+drivers/gpu/drm/i915/gt/selftest_reset.c:137:46:    got void [noderef] __iomem *[assigned] s
+drivers/gpu/drm/i915/gt/selftest_reset.c:137:46: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/i915/gt/selftest_reset.c:98:34:    expected unsigned int [usertype] *s
+drivers/gpu/drm/i915/gt/selftest_reset.c:98:34:    got void [noderef] __iomem *[assigned] s
+drivers/gpu/drm/i915/gt/selftest_reset.c:98:34: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/i915/gvt/mmio.c:295:23: warning: memcpy with byte count of 279040
+drivers/gpu/drm/i915/i915_perf.c:1448:15: warning: memset with byte count of 16777216
+drivers/gpu/drm/i915/i915_perf.c:1502:15: warning: memset with byte count of 16777216
+drivers/gpu/drm/i915/intel_wakeref.c:137:19: warning: context imbalance in 'wakeref_auto_timeout' - unexpected unlock
+./include/linux/seqlock.h:838:24: warning: trying to copy expression type 31
+./include/linux/seqlock.h:838:24: warning: trying to copy expression type 31
+./include/linux/seqlock.h:864:16: warning: trying to copy expression type 31
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write8' - different lock contexts for basic block


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Intel-gfx] ✗ Fi.CI.DOCS: warning for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (10 preceding siblings ...)
  2020-12-10  4:33 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2020-12-10  4:37 ` Patchwork
  2020-12-10  5:02 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2020-12-10  4:37 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
URL   : https://patchwork.freedesktop.org/series/84761/
State : warning

== Summary ==

$ make htmldocs 2>&1 > /dev/null | grep i915
Error: Cannot open file ./drivers/gpu/drm/i915/gt/intel_lrc.c
WARNING: kernel-doc './scripts/kernel-doc -rst -enable-lineno -sphinx-version 1.7.9 -function Logical Rings, Logical Ring Contexts and Execlists ./drivers/gpu/drm/i915/gt/intel_lrc.c' failed with return code 1


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (11 preceding siblings ...)
  2020-12-10  4:37 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
@ 2020-12-10  5:02 ` Patchwork
  2020-12-10  7:11 ` [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
  2020-12-10  7:41 ` [Intel-gfx] ✓ Fi.CI.IGT: success for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header Patchwork
  14 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2020-12-10  5:02 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 3057 bytes --]

== Series Details ==

Series: series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
URL   : https://patchwork.freedesktop.org/series/84761/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_9467 -> Patchwork_19104
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/index.html

Known issues
------------

  Here are the changes found in Patchwork_19104 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_force_connector_basic@force-connector-state:
    - fi-icl-u2:          [PASS][1] -> [DMESG-WARN][2] ([i915#1226])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/fi-icl-u2/igt@kms_force_connector_basic@force-connector-state.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/fi-icl-u2/igt@kms_force_connector_basic@force-connector-state.html

  * igt@prime_self_import@basic-with_two_bos:
    - fi-tgl-y:           [PASS][3] -> [DMESG-WARN][4] ([i915#402])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/fi-tgl-y/igt@prime_self_import@basic-with_two_bos.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/fi-tgl-y/igt@prime_self_import@basic-with_two_bos.html

  
#### Possible fixes ####

  * igt@prime_vgem@basic-userptr:
    - fi-tgl-y:           [DMESG-WARN][5] ([i915#402]) -> [PASS][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/fi-tgl-y/igt@prime_vgem@basic-userptr.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/fi-tgl-y/igt@prime_vgem@basic-userptr.html

  
  [i915#1226]: https://gitlab.freedesktop.org/drm/intel/issues/1226
  [i915#402]: https://gitlab.freedesktop.org/drm/intel/issues/402


Participating hosts (43 -> 40)
------------------------------

  Missing    (3): fi-ilk-m540 fi-bdw-samus fi-hsw-4200u 


Build changes
-------------

  * Linux: CI_DRM_9467 -> Patchwork_19104

  CI-20190529: 20190529
  CI_DRM_9467: 97bdde324e46e276a88de5d2d0c759b4309173c6 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5886: c65fd1fbc26e9f65756d130d33b0ed56bc8faec7 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_19104: 6a72e6f856364a3f11c5b4be843e81acc4b7f6fe @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

6a72e6f85636 drm/i915: migrate skl planes code new file
8fd0727c2a20 drm/i915: migrate hsw fdi code to new file.
3f29deb02bb0 drm/i915: split fdi code out from intel_display.c
3a72e7ca995f drm/i915: refactor pll code out into intel_dpll_legacy.c
cda39caa4c68 drm/i915: refactor some crtc code out of intel display.
e673ce40272b drm/i915: refactor cursor code out of i915_display.c
89c17eeef1fa drm/i915/display: fix misused comma
f7906d61c852 drm/i915/display: move to_intel_frontbuffer to header
ee7dca5fec1e drm/i915/display: move needs_modeset to an inline in header

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/index.html

[-- Attachment #1.2: Type: text/html, Size: 3829 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [RFC v2] refactor intel display a bit more
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (12 preceding siblings ...)
  2020-12-10  5:02 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
@ 2020-12-10  7:11 ` Dave Airlie
  2020-12-10  7:41 ` [Intel-gfx] ✓ Fi.CI.IGT: success for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header Patchwork
  14 siblings, 0 replies; 25+ messages in thread
From: Dave Airlie @ 2020-12-10  7:11 UTC (permalink / raw)
  To: Intel Graphics Development

There are all in this branch
https://github.com/airlied/linux/commits/i915-display-refactor

I moved more code in the skl planes patch and move some pipe code in
there as well

Will repost those tomorrow most likely.

Dave.

On Thu, 10 Dec 2020 at 14:18, Dave Airlie <airlied@gmail.com> wrote:
>
> The first 3 are just moving some functions to inline and fixing
> a wrong comma, the next 4 are cleaned up from yesterday.
>
> hsw fdi is definitely a WIP.
>
> Skl planes migration is along the lines of what danvet asked for.
>
> Dave.
>
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Intel-gfx] ✓ Fi.CI.IGT: success for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
  2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
                   ` (13 preceding siblings ...)
  2020-12-10  7:11 ` [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
@ 2020-12-10  7:41 ` Patchwork
  14 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2020-12-10  7:41 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 16391 bytes --]

== Series Details ==

Series: series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header
URL   : https://patchwork.freedesktop.org/series/84761/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_9467_full -> Patchwork_19104_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Known issues
------------

  Here are the changes found in Patchwork_19104_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_userptr_blits@readonly-pwrite-unsync:
    - shard-iclb:         NOTRUN -> [SKIP][1] ([fdo#110426] / [i915#1704])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@gem_userptr_blits@readonly-pwrite-unsync.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-iclb:         [PASS][2] -> [FAIL][3] ([i915#454])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-iclb7/igt@i915_pm_dc@dc6-psr.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb4/igt@i915_pm_dc@dc6-psr.html

  * igt@kms_async_flips@alternate-sync-async-flip:
    - shard-tglb:         [PASS][4] -> [FAIL][5] ([i915#2521])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-tglb8/igt@kms_async_flips@alternate-sync-async-flip.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-tglb2/igt@kms_async_flips@alternate-sync-async-flip.html

  * igt@kms_big_fb@yf-tiled-64bpp-rotate-0:
    - shard-iclb:         NOTRUN -> [SKIP][6] ([fdo#110723])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_big_fb@yf-tiled-64bpp-rotate-0.html

  * igt@kms_ccs@pipe-c-crc-primary-basic:
    - shard-skl:          NOTRUN -> [SKIP][7] ([fdo#109271] / [fdo#111304])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl6/igt@kms_ccs@pipe-c-crc-primary-basic.html

  * igt@kms_color_chamelium@pipe-c-gamma:
    - shard-skl:          NOTRUN -> [SKIP][8] ([fdo#109271] / [fdo#111827])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl8/igt@kms_color_chamelium@pipe-c-gamma.html

  * igt@kms_color_chamelium@pipe-invalid-ctm-matrix-sizes:
    - shard-iclb:         NOTRUN -> [SKIP][9] ([fdo#109284] / [fdo#111827]) +2 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_color_chamelium@pipe-invalid-ctm-matrix-sizes.html

  * igt@kms_content_protection@srm:
    - shard-iclb:         NOTRUN -> [SKIP][10] ([fdo#109300] / [fdo#111066])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_content_protection@srm.html

  * igt@kms_cursor_crc@pipe-a-cursor-256x256-offscreen:
    - shard-skl:          NOTRUN -> [FAIL][11] ([i915#54])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl6/igt@kms_cursor_crc@pipe-a-cursor-256x256-offscreen.html

  * igt@kms_cursor_crc@pipe-b-cursor-256x256-rapid-movement:
    - shard-kbl:          [PASS][12] -> [DMESG-WARN][13] ([i915#165] / [i915#180])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-kbl6/igt@kms_cursor_crc@pipe-b-cursor-256x256-rapid-movement.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-kbl2/igt@kms_cursor_crc@pipe-b-cursor-256x256-rapid-movement.html

  * igt@kms_cursor_crc@pipe-c-cursor-256x85-sliding:
    - shard-skl:          [PASS][14] -> [FAIL][15] ([i915#54])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-skl7/igt@kms_cursor_crc@pipe-c-cursor-256x85-sliding.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl8/igt@kms_cursor_crc@pipe-c-cursor-256x85-sliding.html

  * igt@kms_cursor_crc@pipe-c-cursor-suspend:
    - shard-kbl:          [PASS][16] -> [DMESG-WARN][17] ([i915#180])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-kbl7/igt@kms_cursor_crc@pipe-c-cursor-suspend.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-kbl1/igt@kms_cursor_crc@pipe-c-cursor-suspend.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-skl:          NOTRUN -> [FAIL][18] ([i915#2346])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl6/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_flip@2x-flip-vs-wf_vblank-interruptible:
    - shard-iclb:         NOTRUN -> [SKIP][19] ([fdo#109274]) +3 similar issues
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_flip@2x-flip-vs-wf_vblank-interruptible.html

  * igt@kms_flip@2x-plain-flip-ts-check-interruptible@ab-hdmi-a1-hdmi-a2:
    - shard-glk:          [PASS][20] -> [FAIL][21] ([i915#2122])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-glk3/igt@kms_flip@2x-plain-flip-ts-check-interruptible@ab-hdmi-a1-hdmi-a2.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-glk2/igt@kms_flip@2x-plain-flip-ts-check-interruptible@ab-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@flip-vs-suspend@c-edp1:
    - shard-skl:          [PASS][22] -> [INCOMPLETE][23] ([i915#198])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-skl7/igt@kms_flip@flip-vs-suspend@c-edp1.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl4/igt@kms_flip@flip-vs-suspend@c-edp1.html

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-pwrite:
    - shard-skl:          NOTRUN -> [SKIP][24] ([fdo#109271]) +23 similar issues
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl6/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-cpu:
    - shard-iclb:         NOTRUN -> [SKIP][25] ([fdo#109280]) +5 similar issues
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-cpu.html

  * igt@kms_hdr@bpc-switch-suspend:
    - shard-skl:          [PASS][26] -> [FAIL][27] ([i915#1188]) +1 similar issue
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-skl3/igt@kms_hdr@bpc-switch-suspend.html
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl10/igt@kms_hdr@bpc-switch-suspend.html

  * igt@kms_plane_alpha_blend@pipe-b-alpha-basic:
    - shard-skl:          NOTRUN -> [FAIL][28] ([fdo#108145] / [i915#265])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl8/igt@kms_plane_alpha_blend@pipe-b-alpha-basic.html

  * igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min:
    - shard-skl:          [PASS][29] -> [FAIL][30] ([fdo#108145] / [i915#265])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-skl6/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl4/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html

  * igt@kms_plane_cursor@pipe-d-primary-size-128:
    - shard-iclb:         NOTRUN -> [SKIP][31] ([fdo#109278]) +5 similar issues
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_plane_cursor@pipe-d-primary-size-128.html

  * igt@kms_psr@psr2_sprite_render:
    - shard-iclb:         [PASS][32] -> [SKIP][33] ([fdo#109441]) +1 similar issue
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-iclb2/igt@kms_psr@psr2_sprite_render.html
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb7/igt@kms_psr@psr2_sprite_render.html

  * igt@nouveau_crc@pipe-d-source-rg:
    - shard-iclb:         NOTRUN -> [SKIP][34] ([fdo#109278] / [i915#2530])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@nouveau_crc@pipe-d-source-rg.html

  * igt@perf@per-context-mode-unprivileged:
    - shard-iclb:         NOTRUN -> [SKIP][35] ([fdo#109289]) +1 similar issue
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@perf@per-context-mode-unprivileged.html

  * igt@prime_vgem@fence-flip-hang:
    - shard-iclb:         NOTRUN -> [SKIP][36] ([fdo#109295])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@prime_vgem@fence-flip-hang.html

  
#### Possible fixes ####

  * igt@gem_exec_whisper@basic-fds-forked:
    - shard-glk:          [DMESG-WARN][37] ([i915#118] / [i915#95]) -> [PASS][38] +1 similar issue
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-glk9/igt@gem_exec_whisper@basic-fds-forked.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-glk2/igt@gem_exec_whisper@basic-fds-forked.html

  * igt@kms_color@pipe-a-gamma:
    - shard-tglb:         [FAIL][39] ([i915#1149]) -> [PASS][40]
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-tglb8/igt@kms_color@pipe-a-gamma.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-tglb6/igt@kms_color@pipe-a-gamma.html

  * igt@kms_cursor_crc@pipe-b-cursor-64x21-offscreen:
    - shard-skl:          [FAIL][41] ([i915#54]) -> [PASS][42] +4 similar issues
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-skl6/igt@kms_cursor_crc@pipe-b-cursor-64x21-offscreen.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl4/igt@kms_cursor_crc@pipe-b-cursor-64x21-offscreen.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@c-dp1:
    - shard-kbl:          [FAIL][43] ([i915#79]) -> [PASS][44]
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-kbl6/igt@kms_flip@flip-vs-expired-vblank-interruptible@c-dp1.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-kbl2/igt@kms_flip@flip-vs-expired-vblank-interruptible@c-dp1.html

  * igt@kms_flip@flip-vs-expired-vblank@a-edp1:
    - shard-tglb:         [FAIL][45] ([i915#2598]) -> [PASS][46]
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-tglb1/igt@kms_flip@flip-vs-expired-vblank@a-edp1.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-tglb3/igt@kms_flip@flip-vs-expired-vblank@a-edp1.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt:
    - shard-snb:          [SKIP][47] ([fdo#109271]) -> [PASS][48] +1 similar issue
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-snb6/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-snb2/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt.html

  * igt@kms_hdr@bpc-switch-dpms:
    - shard-skl:          [FAIL][49] ([i915#1188]) -> [PASS][50]
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-skl3/igt@kms_hdr@bpc-switch-dpms.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl9/igt@kms_hdr@bpc-switch-dpms.html

  * igt@kms_plane_alpha_blend@pipe-b-coverage-7efc:
    - shard-skl:          [FAIL][51] ([fdo#108145] / [i915#265]) -> [PASS][52]
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-skl5/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-skl7/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html

  * igt@kms_psr@psr2_cursor_mmap_cpu:
    - shard-iclb:         [SKIP][53] ([fdo#109441]) -> [PASS][54]
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-iclb3/igt@kms_psr@psr2_cursor_mmap_cpu.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_psr@psr2_cursor_mmap_cpu.html

  * igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend:
    - shard-iclb:         [INCOMPLETE][55] ([i915#1185]) -> [PASS][56]
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-iclb3/igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-iclb2/igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend.html

  
#### Warnings ####

  * igt@i915_suspend@fence-restore-tiled2untiled:
    - shard-kbl:          [DMESG-WARN][57] -> [INCOMPLETE][58] ([i915#155] / [i915#794])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-kbl7/igt@i915_suspend@fence-restore-tiled2untiled.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-kbl6/igt@i915_suspend@fence-restore-tiled2untiled.html

  * igt@runner@aborted:
    - shard-kbl:          ([FAIL][59], [FAIL][60]) ([i915#2295] / [i915#2722] / [i915#483]) -> ([FAIL][61], [FAIL][62]) ([i915#1814] / [i915#2295] / [i915#2722] / [i915#483])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-kbl1/igt@runner@aborted.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9467/shard-kbl7/igt@runner@aborted.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-kbl7/igt@runner@aborted.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/shard-kbl1/igt@runner@aborted.html

  
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109274]: https://bugs.freedesktop.org/show_bug.cgi?id=109274
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109280]: https://bugs.freedesktop.org/show_bug.cgi?id=109280
  [fdo#109284]: https://bugs.freedesktop.org/show_bug.cgi?id=109284
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109295]: https://bugs.freedesktop.org/show_bug.cgi?id=109295
  [fdo#109300]: https://bugs.freedesktop.org/show_bug.cgi?id=109300
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#110426]: https://bugs.freedesktop.org/show_bug.cgi?id=110426
  [fdo#110723]: https://bugs.freedesktop.org/show_bug.cgi?id=110723
  [fdo#111066]: https://bugs.freedesktop.org/show_bug.cgi?id=111066
  [fdo#111304]: https://bugs.freedesktop.org/show_bug.cgi?id=111304
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1149]: https://gitlab.freedesktop.org/drm/intel/issues/1149
  [i915#118]: https://gitlab.freedesktop.org/drm/intel/issues/118
  [i915#1185]: https://gitlab.freedesktop.org/drm/intel/issues/1185
  [i915#1188]: https://gitlab.freedesktop.org/drm/intel/issues/1188
  [i915#155]: https://gitlab.freedesktop.org/drm/intel/issues/155
  [i915#165]: https://gitlab.freedesktop.org/drm/intel/issues/165
  [i915#1704]: https://gitlab.freedesktop.org/drm/intel/issues/1704
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#1814]: https://gitlab.freedesktop.org/drm/intel/issues/1814
  [i915#198]: https://gitlab.freedesktop.org/drm/intel/issues/198
  [i915#2122]: https://gitlab.freedesktop.org/drm/intel/issues/2122
  [i915#2295]: https://gitlab.freedesktop.org/drm/intel/issues/2295
  [i915#2346]: https://gitlab.freedesktop.org/drm/intel/issues/2346
  [i915#2521]: https://gitlab.freedesktop.org/drm/intel/issues/2521
  [i915#2530]: https://gitlab.freedesktop.org/drm/intel/issues/2530
  [i915#2598]: https://gitlab.freedesktop.org/drm/intel/issues/2598
  [i915#265]: https://gitlab.freedesktop.org/drm/intel/issues/265
  [i915#2722]: https://gitlab.freedesktop.org/drm/intel/issues/2722
  [i915#454]: https://gitlab.freedesktop.org/drm/intel/issues/454
  [i915#483]: https://gitlab.freedesktop.org/drm/intel/issues/483
  [i915#54]: https://gitlab.freedesktop.org/drm/intel/issues/54
  [i915#79]: https://gitlab.freedesktop.org/drm/intel/issues/79
  [i915#794]: https://gitlab.freedesktop.org/drm/intel/issues/794
  [i915#95]: https://gitlab.freedesktop.org/drm/intel/issues/95


Participating hosts (10 -> 10)
------------------------------

  No changes in participating hosts


Build changes
-------------

  * Linux: CI_DRM_9467 -> Patchwork_19104

  CI-20190529: 20190529
  CI_DRM_9467: 97bdde324e46e276a88de5d2d0c759b4309173c6 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5886: c65fd1fbc26e9f65756d130d33b0ed56bc8faec7 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_19104: 6a72e6f856364a3f11c5b4be843e81acc4b7f6fe @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19104/index.html

[-- Attachment #1.2: Type: text/html, Size: 19312 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c Dave Airlie
@ 2020-12-10 15:06   ` Ville Syrjälä
  2020-12-10 16:12     ` Jani Nikula
  0 siblings, 1 reply; 25+ messages in thread
From: Ville Syrjälä @ 2020-12-10 15:06 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 02:17:50PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> This file is a monster, let's start simple, the cursor plane code
> seems pretty standalone, and splits out easily enough.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
>  drivers/gpu/drm/i915/Makefile                |   1 +
>  drivers/gpu/drm/i915/display/intel_cursor.c  | 805 +++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_display.c | 796 +-----------------
>  drivers/gpu/drm/i915/display/intel_display.h |  12 +

I would just add the intel_cursor.h for this. intel_display.h is an
even bigger mess than intel_display.c, and causing no end of redundant
rebuilds. The smaller we can make it the better IMO.

Looks like a mechanical move, and seems to match my attempt at it so
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

>  4 files changed, 824 insertions(+), 790 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_cursor.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index e5574e506a5c..98a35b939052 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -197,6 +197,7 @@ i915-y += \
>  	display/intel_combo_phy.o \
>  	display/intel_connector.o \
>  	display/intel_csr.o \
> +	display/intel_cursor.o \
>  	display/intel_display.o \
>  	display/intel_display_power.o \
>  	display/intel_dpio_phy.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
> new file mode 100644
> index 000000000000..87a7a74a25ac
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_cursor.c
> @@ -0,0 +1,805 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +#include <linux/kernel.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_atomic_uapi.h>
> +#include <drm/drm_damage_helper.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_fourcc.h>
> +
> +#include "intel_atomic.h"
> +#include "intel_atomic_plane.h"
> +#include "intel_display_types.h"
> +#include "intel_display.h"
> +
> +#include "intel_frontbuffer.h"
> +#include "intel_pm.h"
> +#include "intel_psr.h"
> +#include "intel_sprite.h"
> +
> +/* Cursor formats */
> +static const u32 intel_cursor_formats[] = {
> +	DRM_FORMAT_ARGB8888,
> +};
> +
> +static const u64 cursor_format_modifiers[] = {
> +	DRM_FORMAT_MOD_LINEAR,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
> +static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv =
> +		to_i915(plane_state->uapi.plane->dev);
> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
> +	const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> +	u32 base;
> +
> +	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
> +		base = sg_dma_address(obj->mm.pages->sgl);
> +	else
> +		base = intel_plane_ggtt_offset(plane_state);
> +
> +	return base + plane_state->color_plane[0].offset;
> +}
> +
> +static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
> +{
> +	int x = plane_state->uapi.dst.x1;
> +	int y = plane_state->uapi.dst.y1;
> +	u32 pos = 0;
> +
> +	if (x < 0) {
> +		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
> +		x = -x;
> +	}
> +	pos |= x << CURSOR_X_SHIFT;
> +
> +	if (y < 0) {
> +		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
> +		y = -y;
> +	}
> +	pos |= y << CURSOR_Y_SHIFT;
> +
> +	return pos;
> +}
> +
> +static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
> +{
> +	const struct drm_mode_config *config =
> +		&plane_state->uapi.plane->dev->mode_config;
> +	int width = drm_rect_width(&plane_state->uapi.dst);
> +	int height = drm_rect_height(&plane_state->uapi.dst);
> +
> +	return width > 0 && width <= config->cursor_width &&
> +		height > 0 && height <= config->cursor_height;
> +}
> +
> +static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv =
> +		to_i915(plane_state->uapi.plane->dev);
> +	unsigned int rotation = plane_state->hw.rotation;
> +	int src_x, src_y;
> +	u32 offset;
> +	int ret;
> +
> +	ret = intel_plane_compute_gtt(plane_state);
> +	if (ret)
> +		return ret;
> +
> +	if (!plane_state->uapi.visible)
> +		return 0;
> +
> +	src_x = plane_state->uapi.src.x1 >> 16;
> +	src_y = plane_state->uapi.src.y1 >> 16;
> +
> +	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
> +	offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
> +						    plane_state, 0);
> +
> +	if (src_x != 0 || src_y != 0) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "Arbitrary cursor panning not supported\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Put the final coordinates back so that the src
> +	 * coordinate checks will see the right values.
> +	 */
> +	drm_rect_translate_to(&plane_state->uapi.src,
> +			      src_x << 16, src_y << 16);
> +
> +	/* ILK+ do this automagically in hardware */
> +	if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
> +		const struct drm_framebuffer *fb = plane_state->hw.fb;
> +		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> +		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
> +
> +		offset += (src_h * src_w - 1) * fb->format->cpp[0];
> +	}
> +
> +	plane_state->color_plane[0].offset = offset;
> +	plane_state->color_plane[0].x = src_x;
> +	plane_state->color_plane[0].y = src_y;
> +
> +	return 0;
> +}
> +
> +static int intel_check_cursor(struct intel_crtc_state *crtc_state,
> +			      struct intel_plane_state *plane_state)
> +{
> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
> +	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> +	const struct drm_rect src = plane_state->uapi.src;
> +	const struct drm_rect dst = plane_state->uapi.dst;
> +	int ret;
> +
> +	if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
> +		drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> +						DRM_PLANE_HELPER_NO_SCALING,
> +						DRM_PLANE_HELPER_NO_SCALING,
> +						true);
> +	if (ret)
> +		return ret;
> +
> +	/* Use the unclipped src/dst rectangles, which we program to hw */
> +	plane_state->uapi.src = src;
> +	plane_state->uapi.dst = dst;
> +
> +	ret = intel_cursor_check_surface(plane_state);
> +	if (ret)
> +		return ret;
> +
> +	if (!plane_state->uapi.visible)
> +		return 0;
> +
> +	ret = intel_plane_check_src_coordinates(plane_state);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static unsigned int
> +i845_cursor_max_stride(struct intel_plane *plane,
> +		       u32 pixel_format, u64 modifier,
> +		       unsigned int rotation)
> +{
> +	return 2048;
> +}
> +
> +static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> +{
> +	u32 cntl = 0;
> +
> +	if (crtc_state->gamma_enable)
> +		cntl |= CURSOR_GAMMA_ENABLE;
> +
> +	return cntl;
> +}
> +
> +static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
> +			   const struct intel_plane_state *plane_state)
> +{
> +	return CURSOR_ENABLE |
> +		CURSOR_FORMAT_ARGB |
> +		CURSOR_STRIDE(plane_state->color_plane[0].stride);
> +}
> +
> +static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
> +{
> +	int width = drm_rect_width(&plane_state->uapi.dst);
> +
> +	/*
> +	 * 845g/865g are only limited by the width of their cursors,
> +	 * the height is arbitrary up to the precision of the register.
> +	 */
> +	return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
> +}
> +
> +static int i845_check_cursor(struct intel_crtc_state *crtc_state,
> +			     struct intel_plane_state *plane_state)
> +{
> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
> +	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> +	int ret;
> +
> +	ret = intel_check_cursor(crtc_state, plane_state);
> +	if (ret)
> +		return ret;
> +
> +	/* if we want to turn off the cursor ignore width and height */
> +	if (!fb)
> +		return 0;
> +
> +	/* Check for which cursor types we support */
> +	if (!i845_cursor_size_ok(plane_state)) {
> +		drm_dbg_kms(&i915->drm,
> +			    "Cursor dimension %dx%d not supported\n",
> +			    drm_rect_width(&plane_state->uapi.dst),
> +			    drm_rect_height(&plane_state->uapi.dst));
> +		return -EINVAL;
> +	}
> +
> +	drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
> +		    plane_state->color_plane[0].stride != fb->pitches[0]);
> +
> +	switch (fb->pitches[0]) {
> +	case 256:
> +	case 512:
> +	case 1024:
> +	case 2048:
> +		break;
> +	default:
> +		 drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
> +			     fb->pitches[0]);
> +		return -EINVAL;
> +	}
> +
> +	plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
> +
> +	return 0;
> +}
> +
> +static void i845_update_cursor(struct intel_plane *plane,
> +			       const struct intel_crtc_state *crtc_state,
> +			       const struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	u32 cntl = 0, base = 0, pos = 0, size = 0;
> +	unsigned long irqflags;
> +
> +	if (plane_state && plane_state->uapi.visible) {
> +		unsigned int width = drm_rect_width(&plane_state->uapi.dst);
> +		unsigned int height = drm_rect_height(&plane_state->uapi.dst);
> +
> +		cntl = plane_state->ctl |
> +			i845_cursor_ctl_crtc(crtc_state);
> +
> +		size = (height << 12) | width;
> +
> +		base = intel_cursor_base(plane_state);
> +		pos = intel_cursor_position(plane_state);
> +	}
> +
> +	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> +	/* On these chipsets we can only modify the base/size/stride
> +	 * whilst the cursor is disabled.
> +	 */
> +	if (plane->cursor.base != base ||
> +	    plane->cursor.size != size ||
> +	    plane->cursor.cntl != cntl) {
> +		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
> +		intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
> +		intel_de_write_fw(dev_priv, CURSIZE, size);
> +		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> +		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
> +
> +		plane->cursor.base = base;
> +		plane->cursor.size = size;
> +		plane->cursor.cntl = cntl;
> +	} else {
> +		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> +	}
> +
> +	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static void i845_disable_cursor(struct intel_plane *plane,
> +				const struct intel_crtc_state *crtc_state)
> +{
> +	i845_update_cursor(plane, crtc_state, NULL);
> +}
> +
> +static bool i845_cursor_get_hw_state(struct intel_plane *plane,
> +				     enum pipe *pipe)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
> +	bool ret;
> +
> +	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
> +		return false;
> +
> +	ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
> +
> +	*pipe = PIPE_A;
> +
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
> +
> +	return ret;
> +}
> +
> +static unsigned int
> +i9xx_cursor_max_stride(struct intel_plane *plane,
> +		       u32 pixel_format, u64 modifier,
> +		       unsigned int rotation)
> +{
> +	return plane->base.dev->mode_config.cursor_width * 4;
> +}
> +
> +static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	u32 cntl = 0;
> +
> +	if (INTEL_GEN(dev_priv) >= 11)
> +		return cntl;
> +
> +	if (crtc_state->gamma_enable)
> +		cntl = MCURSOR_GAMMA_ENABLE;
> +
> +	if (crtc_state->csc_enable)
> +		cntl |= MCURSOR_PIPE_CSC_ENABLE;
> +
> +	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
> +		cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
> +
> +	return cntl;
> +}
> +
> +static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
> +			   const struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv =
> +		to_i915(plane_state->uapi.plane->dev);
> +	u32 cntl = 0;
> +
> +	if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> +		cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
> +
> +	switch (drm_rect_width(&plane_state->uapi.dst)) {
> +	case 64:
> +		cntl |= MCURSOR_MODE_64_ARGB_AX;
> +		break;
> +	case 128:
> +		cntl |= MCURSOR_MODE_128_ARGB_AX;
> +		break;
> +	case 256:
> +		cntl |= MCURSOR_MODE_256_ARGB_AX;
> +		break;
> +	default:
> +		MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
> +		return 0;
> +	}
> +
> +	if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
> +		cntl |= MCURSOR_ROTATE_180;
> +
> +	return cntl;
> +}
> +
> +static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv =
> +		to_i915(plane_state->uapi.plane->dev);
> +	int width = drm_rect_width(&plane_state->uapi.dst);
> +	int height = drm_rect_height(&plane_state->uapi.dst);
> +
> +	if (!intel_cursor_size_ok(plane_state))
> +		return false;
> +
> +	/* Cursor width is limited to a few power-of-two sizes */
> +	switch (width) {
> +	case 256:
> +	case 128:
> +	case 64:
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	/*
> +	 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
> +	 * height from 8 lines up to the cursor width, when the
> +	 * cursor is not rotated. Everything else requires square
> +	 * cursors.
> +	 */
> +	if (HAS_CUR_FBC(dev_priv) &&
> +	    plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
> +		if (height < 8 || height > width)
> +			return false;
> +	} else {
> +		if (height != width)
> +			return false;
> +	}
> +
> +	return true;
> +}
> +
> +static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
> +			     struct intel_plane_state *plane_state)
> +{
> +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
> +	enum pipe pipe = plane->pipe;
> +	int ret;
> +
> +	ret = intel_check_cursor(crtc_state, plane_state);
> +	if (ret)
> +		return ret;
> +
> +	/* if we want to turn off the cursor ignore width and height */
> +	if (!fb)
> +		return 0;
> +
> +	/* Check for which cursor types we support */
> +	if (!i9xx_cursor_size_ok(plane_state)) {
> +		drm_dbg(&dev_priv->drm,
> +			"Cursor dimension %dx%d not supported\n",
> +			drm_rect_width(&plane_state->uapi.dst),
> +			drm_rect_height(&plane_state->uapi.dst));
> +		return -EINVAL;
> +	}
> +
> +	drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
> +		    plane_state->color_plane[0].stride != fb->pitches[0]);
> +
> +	if (fb->pitches[0] !=
> +	    drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "Invalid cursor stride (%u) (cursor width %d)\n",
> +			    fb->pitches[0],
> +			    drm_rect_width(&plane_state->uapi.dst));
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * There's something wrong with the cursor on CHV pipe C.
> +	 * If it straddles the left edge of the screen then
> +	 * moving it away from the edge or disabling it often
> +	 * results in a pipe underrun, and often that can lead to
> +	 * dead pipe (constant underrun reported, and it scans
> +	 * out just a solid color). To recover from that, the
> +	 * display power well must be turned off and on again.
> +	 * Refuse the put the cursor into that compromised position.
> +	 */
> +	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
> +	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "CHV cursor C not allowed to straddle the left screen edge\n");
> +		return -EINVAL;
> +	}
> +
> +	plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
> +
> +	return 0;
> +}
> +
> +static void i9xx_update_cursor(struct intel_plane *plane,
> +			       const struct intel_crtc_state *crtc_state,
> +			       const struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	enum pipe pipe = plane->pipe;
> +	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
> +	unsigned long irqflags;
> +
> +	if (plane_state && plane_state->uapi.visible) {
> +		unsigned width = drm_rect_width(&plane_state->uapi.dst);
> +		unsigned height = drm_rect_height(&plane_state->uapi.dst);
> +
> +		cntl = plane_state->ctl |
> +			i9xx_cursor_ctl_crtc(crtc_state);
> +
> +		if (width != height)
> +			fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
> +
> +		base = intel_cursor_base(plane_state);
> +		pos = intel_cursor_position(plane_state);
> +	}
> +
> +	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> +	/*
> +	 * On some platforms writing CURCNTR first will also
> +	 * cause CURPOS to be armed by the CURBASE write.
> +	 * Without the CURCNTR write the CURPOS write would
> +	 * arm itself. Thus we always update CURCNTR before
> +	 * CURPOS.
> +	 *
> +	 * On other platforms CURPOS always requires the
> +	 * CURBASE write to arm the update. Additonally
> +	 * a write to any of the cursor register will cancel
> +	 * an already armed cursor update. Thus leaving out
> +	 * the CURBASE write after CURPOS could lead to a
> +	 * cursor that doesn't appear to move, or even change
> +	 * shape. Thus we always write CURBASE.
> +	 *
> +	 * The other registers are armed by by the CURBASE write
> +	 * except when the plane is getting enabled at which time
> +	 * the CURCNTR write arms the update.
> +	 */
> +
> +	if (INTEL_GEN(dev_priv) >= 9)
> +		skl_write_cursor_wm(plane, crtc_state);
> +
> +	if (!intel_crtc_needs_modeset(crtc_state))
> +		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
> +
> +	if (plane->cursor.base != base ||
> +	    plane->cursor.size != fbc_ctl ||
> +	    plane->cursor.cntl != cntl) {
> +		if (HAS_CUR_FBC(dev_priv))
> +			intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
> +					  fbc_ctl);
> +		intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
> +		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> +		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> +
> +		plane->cursor.base = base;
> +		plane->cursor.size = fbc_ctl;
> +		plane->cursor.cntl = cntl;
> +	} else {
> +		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> +		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> +	}
> +
> +	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static void i9xx_disable_cursor(struct intel_plane *plane,
> +				const struct intel_crtc_state *crtc_state)
> +{
> +	i9xx_update_cursor(plane, crtc_state, NULL);
> +}
> +
> +static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
> +				     enum pipe *pipe)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
> +	bool ret;
> +	u32 val;
> +
> +	/*
> +	 * Not 100% correct for planes that can move between pipes,
> +	 * but that's only the case for gen2-3 which don't have any
> +	 * display power wells.
> +	 */
> +	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
> +		return false;
> +
> +	val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
> +
> +	ret = val & MCURSOR_MODE;
> +
> +	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> +		*pipe = plane->pipe;
> +	else
> +		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
> +			MCURSOR_PIPE_SELECT_SHIFT;
> +
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
> +
> +	return ret;
> +}
> +
> +static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
> +					      u32 format, u64 modifier)
> +{
> +	return modifier == DRM_FORMAT_MOD_LINEAR &&
> +		format == DRM_FORMAT_ARGB8888;
> +}
> +
> +static int
> +intel_legacy_cursor_update(struct drm_plane *_plane,
> +			   struct drm_crtc *_crtc,
> +			   struct drm_framebuffer *fb,
> +			   int crtc_x, int crtc_y,
> +			   unsigned int crtc_w, unsigned int crtc_h,
> +			   u32 src_x, u32 src_y,
> +			   u32 src_w, u32 src_h,
> +			   struct drm_modeset_acquire_ctx *ctx)
> +{
> +	struct intel_plane *plane = to_intel_plane(_plane);
> +	struct intel_crtc *crtc = to_intel_crtc(_crtc);
> +	struct intel_plane_state *old_plane_state =
> +		to_intel_plane_state(plane->base.state);
> +	struct intel_plane_state *new_plane_state;
> +	struct intel_crtc_state *crtc_state =
> +		to_intel_crtc_state(crtc->base.state);
> +	struct intel_crtc_state *new_crtc_state;
> +	int ret;
> +
> +	/*
> +	 * When crtc is inactive or there is a modeset pending,
> +	 * wait for it to complete in the slowpath
> +	 *
> +	 * FIXME bigjoiner fastpath would be good
> +	 */
> +	if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
> +	    crtc_state->update_pipe || crtc_state->bigjoiner)
> +		goto slow;
> +
> +	/*
> +	 * Don't do an async update if there is an outstanding commit modifying
> +	 * the plane.  This prevents our async update's changes from getting
> +	 * overridden by a previous synchronous update's state.
> +	 */
> +	if (old_plane_state->uapi.commit &&
> +	    !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
> +		goto slow;
> +
> +	/*
> +	 * If any parameters change that may affect watermarks,
> +	 * take the slowpath. Only changing fb or position should be
> +	 * in the fastpath.
> +	 */
> +	if (old_plane_state->uapi.crtc != &crtc->base ||
> +	    old_plane_state->uapi.src_w != src_w ||
> +	    old_plane_state->uapi.src_h != src_h ||
> +	    old_plane_state->uapi.crtc_w != crtc_w ||
> +	    old_plane_state->uapi.crtc_h != crtc_h ||
> +	    !old_plane_state->uapi.fb != !fb)
> +		goto slow;
> +
> +	new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
> +	if (!new_plane_state)
> +		return -ENOMEM;
> +
> +	new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
> +	if (!new_crtc_state) {
> +		ret = -ENOMEM;
> +		goto out_free;
> +	}
> +
> +	drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
> +
> +	new_plane_state->uapi.src_x = src_x;
> +	new_plane_state->uapi.src_y = src_y;
> +	new_plane_state->uapi.src_w = src_w;
> +	new_plane_state->uapi.src_h = src_h;
> +	new_plane_state->uapi.crtc_x = crtc_x;
> +	new_plane_state->uapi.crtc_y = crtc_y;
> +	new_plane_state->uapi.crtc_w = crtc_w;
> +	new_plane_state->uapi.crtc_h = crtc_h;
> +
> +	intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
> +
> +	ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
> +						  old_plane_state, new_plane_state);
> +	if (ret)
> +		goto out_free;
> +
> +	ret = intel_plane_pin_fb(new_plane_state);
> +	if (ret)
> +		goto out_free;
> +
> +	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
> +				ORIGIN_FLIP);
> +	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
> +				to_intel_frontbuffer(new_plane_state->hw.fb),
> +				plane->frontbuffer_bit);
> +
> +	/* Swap plane state */
> +	plane->base.state = &new_plane_state->uapi;
> +
> +	/*
> +	 * We cannot swap crtc_state as it may be in use by an atomic commit or
> +	 * page flip that's running simultaneously. If we swap crtc_state and
> +	 * destroy the old state, we will cause a use-after-free there.
> +	 *
> +	 * Only update active_planes, which is needed for our internal
> +	 * bookkeeping. Either value will do the right thing when updating
> +	 * planes atomically. If the cursor was part of the atomic update then
> +	 * we would have taken the slowpath.
> +	 */
> +	crtc_state->active_planes = new_crtc_state->active_planes;
> +
> +	if (new_plane_state->uapi.visible)
> +		intel_update_plane(plane, crtc_state, new_plane_state);
> +	else
> +		intel_disable_plane(plane, crtc_state);
> +
> +	intel_plane_unpin_fb(old_plane_state);
> +
> +out_free:
> +	if (new_crtc_state)
> +		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
> +	if (ret)
> +		intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
> +	else
> +		intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
> +	return ret;
> +
> +slow:
> +	return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
> +					      crtc_x, crtc_y, crtc_w, crtc_h,
> +					      src_x, src_y, src_w, src_h, ctx);
> +}
> +
> +static const struct drm_plane_funcs intel_cursor_plane_funcs = {
> +	.update_plane = intel_legacy_cursor_update,
> +	.disable_plane = drm_atomic_helper_disable_plane,
> +	.destroy = intel_plane_destroy,
> +	.atomic_duplicate_state = intel_plane_duplicate_state,
> +	.atomic_destroy_state = intel_plane_destroy_state,
> +	.format_mod_supported = intel_cursor_format_mod_supported,
> +};
> +
> +struct intel_plane *
> +intel_cursor_plane_create(struct drm_i915_private *dev_priv,
> +			  enum pipe pipe)
> +{
> +	struct intel_plane *cursor;
> +	int ret, zpos;
> +
> +	cursor = intel_plane_alloc();
> +	if (IS_ERR(cursor))
> +		return cursor;
> +
> +	cursor->pipe = pipe;
> +	cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
> +	cursor->id = PLANE_CURSOR;
> +	cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
> +
> +	if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
> +		cursor->max_stride = i845_cursor_max_stride;
> +		cursor->update_plane = i845_update_cursor;
> +		cursor->disable_plane = i845_disable_cursor;
> +		cursor->get_hw_state = i845_cursor_get_hw_state;
> +		cursor->check_plane = i845_check_cursor;
> +	} else {
> +		cursor->max_stride = i9xx_cursor_max_stride;
> +		cursor->update_plane = i9xx_update_cursor;
> +		cursor->disable_plane = i9xx_disable_cursor;
> +		cursor->get_hw_state = i9xx_cursor_get_hw_state;
> +		cursor->check_plane = i9xx_check_cursor;
> +	}
> +
> +	cursor->cursor.base = ~0;
> +	cursor->cursor.cntl = ~0;
> +
> +	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
> +		cursor->cursor.size = ~0;
> +
> +	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
> +				       0, &intel_cursor_plane_funcs,
> +				       intel_cursor_formats,
> +				       ARRAY_SIZE(intel_cursor_formats),
> +				       cursor_format_modifiers,
> +				       DRM_PLANE_TYPE_CURSOR,
> +				       "cursor %c", pipe_name(pipe));
> +	if (ret)
> +		goto fail;
> +
> +	if (INTEL_GEN(dev_priv) >= 4)
> +		drm_plane_create_rotation_property(&cursor->base,
> +						   DRM_MODE_ROTATE_0,
> +						   DRM_MODE_ROTATE_0 |
> +						   DRM_MODE_ROTATE_180);
> +
> +	zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
> +	drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
> +
> +	if (INTEL_GEN(dev_priv) >= 12)
> +		drm_plane_enable_fb_damage_clips(&cursor->base);
> +
> +	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
> +
> +	return cursor;
> +
> +fail:
> +	intel_plane_free(cursor);
> +
> +	return ERR_PTR(ret);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 79d7479beed2..722a1cf61941 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -137,16 +137,6 @@ static const u64 i9xx_format_modifiers[] = {
>  	DRM_FORMAT_MOD_INVALID
>  };
>  
> -/* Cursor formats */
> -static const u32 intel_cursor_formats[] = {
> -	DRM_FORMAT_ARGB8888,
> -};
> -
> -static const u64 cursor_format_modifiers[] = {
> -	DRM_FORMAT_MOD_LINEAR,
> -	DRM_FORMAT_MOD_INVALID
> -};
> -
>  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
>  				struct intel_crtc_state *pipe_config);
>  static void ilk_pch_clock_get(struct intel_crtc *crtc,
> @@ -2528,9 +2518,9 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,
>  	return offset_aligned;
>  }
>  
> -static u32 intel_plane_compute_aligned_offset(int *x, int *y,
> -					      const struct intel_plane_state *state,
> -					      int color_plane)
> +u32 intel_plane_compute_aligned_offset(int *x, int *y,
> +				       const struct intel_plane_state *state,
> +				       int color_plane)
>  {
>  	struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane);
>  	struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
> @@ -3267,7 +3257,7 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)
>  	}
>  }
>  
> -static int
> +int
>  intel_plane_compute_gtt(struct intel_plane_state *plane_state)
>  {
>  	const struct intel_framebuffer *fb =
> @@ -11536,569 +11526,6 @@ static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state)
>  	return true;
>  }
>  
> -static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv =
> -		to_i915(plane_state->uapi.plane->dev);
> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
> -	const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> -	u32 base;
> -
> -	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
> -		base = sg_dma_address(obj->mm.pages->sgl);
> -	else
> -		base = intel_plane_ggtt_offset(plane_state);
> -
> -	return base + plane_state->color_plane[0].offset;
> -}
> -
> -static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
> -{
> -	int x = plane_state->uapi.dst.x1;
> -	int y = plane_state->uapi.dst.y1;
> -	u32 pos = 0;
> -
> -	if (x < 0) {
> -		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
> -		x = -x;
> -	}
> -	pos |= x << CURSOR_X_SHIFT;
> -
> -	if (y < 0) {
> -		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
> -		y = -y;
> -	}
> -	pos |= y << CURSOR_Y_SHIFT;
> -
> -	return pos;
> -}
> -
> -static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
> -{
> -	const struct drm_mode_config *config =
> -		&plane_state->uapi.plane->dev->mode_config;
> -	int width = drm_rect_width(&plane_state->uapi.dst);
> -	int height = drm_rect_height(&plane_state->uapi.dst);
> -
> -	return width > 0 && width <= config->cursor_width &&
> -		height > 0 && height <= config->cursor_height;
> -}
> -
> -static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv =
> -		to_i915(plane_state->uapi.plane->dev);
> -	unsigned int rotation = plane_state->hw.rotation;
> -	int src_x, src_y;
> -	u32 offset;
> -	int ret;
> -
> -	ret = intel_plane_compute_gtt(plane_state);
> -	if (ret)
> -		return ret;
> -
> -	if (!plane_state->uapi.visible)
> -		return 0;
> -
> -	src_x = plane_state->uapi.src.x1 >> 16;
> -	src_y = plane_state->uapi.src.y1 >> 16;
> -
> -	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
> -	offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
> -						    plane_state, 0);
> -
> -	if (src_x != 0 || src_y != 0) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "Arbitrary cursor panning not supported\n");
> -		return -EINVAL;
> -	}
> -
> -	/*
> -	 * Put the final coordinates back so that the src
> -	 * coordinate checks will see the right values.
> -	 */
> -	drm_rect_translate_to(&plane_state->uapi.src,
> -			      src_x << 16, src_y << 16);
> -
> -	/* ILK+ do this automagically in hardware */
> -	if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
> -		const struct drm_framebuffer *fb = plane_state->hw.fb;
> -		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> -		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
> -
> -		offset += (src_h * src_w - 1) * fb->format->cpp[0];
> -	}
> -
> -	plane_state->color_plane[0].offset = offset;
> -	plane_state->color_plane[0].x = src_x;
> -	plane_state->color_plane[0].y = src_y;
> -
> -	return 0;
> -}
> -
> -static int intel_check_cursor(struct intel_crtc_state *crtc_state,
> -			      struct intel_plane_state *plane_state)
> -{
> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
> -	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> -	const struct drm_rect src = plane_state->uapi.src;
> -	const struct drm_rect dst = plane_state->uapi.dst;
> -	int ret;
> -
> -	if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
> -		drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
> -		return -EINVAL;
> -	}
> -
> -	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> -						DRM_PLANE_HELPER_NO_SCALING,
> -						DRM_PLANE_HELPER_NO_SCALING,
> -						true);
> -	if (ret)
> -		return ret;
> -
> -	/* Use the unclipped src/dst rectangles, which we program to hw */
> -	plane_state->uapi.src = src;
> -	plane_state->uapi.dst = dst;
> -
> -	ret = intel_cursor_check_surface(plane_state);
> -	if (ret)
> -		return ret;
> -
> -	if (!plane_state->uapi.visible)
> -		return 0;
> -
> -	ret = intel_plane_check_src_coordinates(plane_state);
> -	if (ret)
> -		return ret;
> -
> -	return 0;
> -}
> -
> -static unsigned int
> -i845_cursor_max_stride(struct intel_plane *plane,
> -		       u32 pixel_format, u64 modifier,
> -		       unsigned int rotation)
> -{
> -	return 2048;
> -}
> -
> -static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> -{
> -	u32 cntl = 0;
> -
> -	if (crtc_state->gamma_enable)
> -		cntl |= CURSOR_GAMMA_ENABLE;
> -
> -	return cntl;
> -}
> -
> -static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
> -			   const struct intel_plane_state *plane_state)
> -{
> -	return CURSOR_ENABLE |
> -		CURSOR_FORMAT_ARGB |
> -		CURSOR_STRIDE(plane_state->color_plane[0].stride);
> -}
> -
> -static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
> -{
> -	int width = drm_rect_width(&plane_state->uapi.dst);
> -
> -	/*
> -	 * 845g/865g are only limited by the width of their cursors,
> -	 * the height is arbitrary up to the precision of the register.
> -	 */
> -	return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
> -}
> -
> -static int i845_check_cursor(struct intel_crtc_state *crtc_state,
> -			     struct intel_plane_state *plane_state)
> -{
> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
> -	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> -	int ret;
> -
> -	ret = intel_check_cursor(crtc_state, plane_state);
> -	if (ret)
> -		return ret;
> -
> -	/* if we want to turn off the cursor ignore width and height */
> -	if (!fb)
> -		return 0;
> -
> -	/* Check for which cursor types we support */
> -	if (!i845_cursor_size_ok(plane_state)) {
> -		drm_dbg_kms(&i915->drm,
> -			    "Cursor dimension %dx%d not supported\n",
> -			    drm_rect_width(&plane_state->uapi.dst),
> -			    drm_rect_height(&plane_state->uapi.dst));
> -		return -EINVAL;
> -	}
> -
> -	drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
> -		    plane_state->color_plane[0].stride != fb->pitches[0]);
> -
> -	switch (fb->pitches[0]) {
> -	case 256:
> -	case 512:
> -	case 1024:
> -	case 2048:
> -		break;
> -	default:
> -		 drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
> -			     fb->pitches[0]);
> -		return -EINVAL;
> -	}
> -
> -	plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
> -
> -	return 0;
> -}
> -
> -static void i845_update_cursor(struct intel_plane *plane,
> -			       const struct intel_crtc_state *crtc_state,
> -			       const struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	u32 cntl = 0, base = 0, pos = 0, size = 0;
> -	unsigned long irqflags;
> -
> -	if (plane_state && plane_state->uapi.visible) {
> -		unsigned int width = drm_rect_width(&plane_state->uapi.dst);
> -		unsigned int height = drm_rect_height(&plane_state->uapi.dst);
> -
> -		cntl = plane_state->ctl |
> -			i845_cursor_ctl_crtc(crtc_state);
> -
> -		size = (height << 12) | width;
> -
> -		base = intel_cursor_base(plane_state);
> -		pos = intel_cursor_position(plane_state);
> -	}
> -
> -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> -	/* On these chipsets we can only modify the base/size/stride
> -	 * whilst the cursor is disabled.
> -	 */
> -	if (plane->cursor.base != base ||
> -	    plane->cursor.size != size ||
> -	    plane->cursor.cntl != cntl) {
> -		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
> -		intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
> -		intel_de_write_fw(dev_priv, CURSIZE, size);
> -		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> -		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
> -
> -		plane->cursor.base = base;
> -		plane->cursor.size = size;
> -		plane->cursor.cntl = cntl;
> -	} else {
> -		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> -	}
> -
> -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static void i845_disable_cursor(struct intel_plane *plane,
> -				const struct intel_crtc_state *crtc_state)
> -{
> -	i845_update_cursor(plane, crtc_state, NULL);
> -}
> -
> -static bool i845_cursor_get_hw_state(struct intel_plane *plane,
> -				     enum pipe *pipe)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	enum intel_display_power_domain power_domain;
> -	intel_wakeref_t wakeref;
> -	bool ret;
> -
> -	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
> -	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> -	if (!wakeref)
> -		return false;
> -
> -	ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
> -
> -	*pipe = PIPE_A;
> -
> -	intel_display_power_put(dev_priv, power_domain, wakeref);
> -
> -	return ret;
> -}
> -
> -static unsigned int
> -i9xx_cursor_max_stride(struct intel_plane *plane,
> -		       u32 pixel_format, u64 modifier,
> -		       unsigned int rotation)
> -{
> -	return plane->base.dev->mode_config.cursor_width * 4;
> -}
> -
> -static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> -{
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -	u32 cntl = 0;
> -
> -	if (INTEL_GEN(dev_priv) >= 11)
> -		return cntl;
> -
> -	if (crtc_state->gamma_enable)
> -		cntl = MCURSOR_GAMMA_ENABLE;
> -
> -	if (crtc_state->csc_enable)
> -		cntl |= MCURSOR_PIPE_CSC_ENABLE;
> -
> -	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
> -		cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
> -
> -	return cntl;
> -}
> -
> -static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
> -			   const struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv =
> -		to_i915(plane_state->uapi.plane->dev);
> -	u32 cntl = 0;
> -
> -	if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> -		cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
> -
> -	switch (drm_rect_width(&plane_state->uapi.dst)) {
> -	case 64:
> -		cntl |= MCURSOR_MODE_64_ARGB_AX;
> -		break;
> -	case 128:
> -		cntl |= MCURSOR_MODE_128_ARGB_AX;
> -		break;
> -	case 256:
> -		cntl |= MCURSOR_MODE_256_ARGB_AX;
> -		break;
> -	default:
> -		MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
> -		return 0;
> -	}
> -
> -	if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
> -		cntl |= MCURSOR_ROTATE_180;
> -
> -	return cntl;
> -}
> -
> -static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv =
> -		to_i915(plane_state->uapi.plane->dev);
> -	int width = drm_rect_width(&plane_state->uapi.dst);
> -	int height = drm_rect_height(&plane_state->uapi.dst);
> -
> -	if (!intel_cursor_size_ok(plane_state))
> -		return false;
> -
> -	/* Cursor width is limited to a few power-of-two sizes */
> -	switch (width) {
> -	case 256:
> -	case 128:
> -	case 64:
> -		break;
> -	default:
> -		return false;
> -	}
> -
> -	/*
> -	 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
> -	 * height from 8 lines up to the cursor width, when the
> -	 * cursor is not rotated. Everything else requires square
> -	 * cursors.
> -	 */
> -	if (HAS_CUR_FBC(dev_priv) &&
> -	    plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
> -		if (height < 8 || height > width)
> -			return false;
> -	} else {
> -		if (height != width)
> -			return false;
> -	}
> -
> -	return true;
> -}
> -
> -static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
> -			     struct intel_plane_state *plane_state)
> -{
> -	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
> -	enum pipe pipe = plane->pipe;
> -	int ret;
> -
> -	ret = intel_check_cursor(crtc_state, plane_state);
> -	if (ret)
> -		return ret;
> -
> -	/* if we want to turn off the cursor ignore width and height */
> -	if (!fb)
> -		return 0;
> -
> -	/* Check for which cursor types we support */
> -	if (!i9xx_cursor_size_ok(plane_state)) {
> -		drm_dbg(&dev_priv->drm,
> -			"Cursor dimension %dx%d not supported\n",
> -			drm_rect_width(&plane_state->uapi.dst),
> -			drm_rect_height(&plane_state->uapi.dst));
> -		return -EINVAL;
> -	}
> -
> -	drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
> -		    plane_state->color_plane[0].stride != fb->pitches[0]);
> -
> -	if (fb->pitches[0] !=
> -	    drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "Invalid cursor stride (%u) (cursor width %d)\n",
> -			    fb->pitches[0],
> -			    drm_rect_width(&plane_state->uapi.dst));
> -		return -EINVAL;
> -	}
> -
> -	/*
> -	 * There's something wrong with the cursor on CHV pipe C.
> -	 * If it straddles the left edge of the screen then
> -	 * moving it away from the edge or disabling it often
> -	 * results in a pipe underrun, and often that can lead to
> -	 * dead pipe (constant underrun reported, and it scans
> -	 * out just a solid color). To recover from that, the
> -	 * display power well must be turned off and on again.
> -	 * Refuse the put the cursor into that compromised position.
> -	 */
> -	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
> -	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "CHV cursor C not allowed to straddle the left screen edge\n");
> -		return -EINVAL;
> -	}
> -
> -	plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
> -
> -	return 0;
> -}
> -
> -static void i9xx_update_cursor(struct intel_plane *plane,
> -			       const struct intel_crtc_state *crtc_state,
> -			       const struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	enum pipe pipe = plane->pipe;
> -	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
> -	unsigned long irqflags;
> -
> -	if (plane_state && plane_state->uapi.visible) {
> -		unsigned width = drm_rect_width(&plane_state->uapi.dst);
> -		unsigned height = drm_rect_height(&plane_state->uapi.dst);
> -
> -		cntl = plane_state->ctl |
> -			i9xx_cursor_ctl_crtc(crtc_state);
> -
> -		if (width != height)
> -			fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
> -
> -		base = intel_cursor_base(plane_state);
> -		pos = intel_cursor_position(plane_state);
> -	}
> -
> -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> -	/*
> -	 * On some platforms writing CURCNTR first will also
> -	 * cause CURPOS to be armed by the CURBASE write.
> -	 * Without the CURCNTR write the CURPOS write would
> -	 * arm itself. Thus we always update CURCNTR before
> -	 * CURPOS.
> -	 *
> -	 * On other platforms CURPOS always requires the
> -	 * CURBASE write to arm the update. Additonally
> -	 * a write to any of the cursor register will cancel
> -	 * an already armed cursor update. Thus leaving out
> -	 * the CURBASE write after CURPOS could lead to a
> -	 * cursor that doesn't appear to move, or even change
> -	 * shape. Thus we always write CURBASE.
> -	 *
> -	 * The other registers are armed by by the CURBASE write
> -	 * except when the plane is getting enabled at which time
> -	 * the CURCNTR write arms the update.
> -	 */
> -
> -	if (INTEL_GEN(dev_priv) >= 9)
> -		skl_write_cursor_wm(plane, crtc_state);
> -
> -	if (!intel_crtc_needs_modeset(crtc_state))
> -		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
> -
> -	if (plane->cursor.base != base ||
> -	    plane->cursor.size != fbc_ctl ||
> -	    plane->cursor.cntl != cntl) {
> -		if (HAS_CUR_FBC(dev_priv))
> -			intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
> -					  fbc_ctl);
> -		intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
> -		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> -		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> -
> -		plane->cursor.base = base;
> -		plane->cursor.size = fbc_ctl;
> -		plane->cursor.cntl = cntl;
> -	} else {
> -		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> -		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> -	}
> -
> -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static void i9xx_disable_cursor(struct intel_plane *plane,
> -				const struct intel_crtc_state *crtc_state)
> -{
> -	i9xx_update_cursor(plane, crtc_state, NULL);
> -}
> -
> -static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
> -				     enum pipe *pipe)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	enum intel_display_power_domain power_domain;
> -	intel_wakeref_t wakeref;
> -	bool ret;
> -	u32 val;
> -
> -	/*
> -	 * Not 100% correct for planes that can move between pipes,
> -	 * but that's only the case for gen2-3 which don't have any
> -	 * display power wells.
> -	 */
> -	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> -	if (!wakeref)
> -		return false;
> -
> -	val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
> -
> -	ret = val & MCURSOR_MODE;
> -
> -	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> -		*pipe = plane->pipe;
> -	else
> -		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
> -			MCURSOR_PIPE_SELECT_SHIFT;
> -
> -	intel_display_power_put(dev_priv, power_domain, wakeref);
> -
> -	return ret;
> -}
> -
>  /* VESA 640x480x72Hz mode to set on the pipe */
>  static const struct drm_display_mode load_detect_mode = {
>  	DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
> @@ -16609,7 +16036,7 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc,
>  	add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
>  }
>  
> -static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
> +int intel_plane_pin_fb(struct intel_plane_state *plane_state)
>  {
>  	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> @@ -16639,7 +16066,7 @@ static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
>  	return 0;
>  }
>  
> -static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
> +void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
>  {
>  	struct i915_vma *vma;
>  
> @@ -16875,13 +16302,6 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
>  	}
>  }
>  
> -static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
> -					      u32 format, u64 modifier)
> -{
> -	return modifier == DRM_FORMAT_MOD_LINEAR &&
> -		format == DRM_FORMAT_ARGB8888;
> -}
> -
>  static const struct drm_plane_funcs i965_plane_funcs = {
>  	.update_plane = drm_atomic_helper_update_plane,
>  	.disable_plane = drm_atomic_helper_disable_plane,
> @@ -16900,142 +16320,6 @@ static const struct drm_plane_funcs i8xx_plane_funcs = {
>  	.format_mod_supported = i8xx_plane_format_mod_supported,
>  };
>  
> -static int
> -intel_legacy_cursor_update(struct drm_plane *_plane,
> -			   struct drm_crtc *_crtc,
> -			   struct drm_framebuffer *fb,
> -			   int crtc_x, int crtc_y,
> -			   unsigned int crtc_w, unsigned int crtc_h,
> -			   u32 src_x, u32 src_y,
> -			   u32 src_w, u32 src_h,
> -			   struct drm_modeset_acquire_ctx *ctx)
> -{
> -	struct intel_plane *plane = to_intel_plane(_plane);
> -	struct intel_crtc *crtc = to_intel_crtc(_crtc);
> -	struct intel_plane_state *old_plane_state =
> -		to_intel_plane_state(plane->base.state);
> -	struct intel_plane_state *new_plane_state;
> -	struct intel_crtc_state *crtc_state =
> -		to_intel_crtc_state(crtc->base.state);
> -	struct intel_crtc_state *new_crtc_state;
> -	int ret;
> -
> -	/*
> -	 * When crtc is inactive or there is a modeset pending,
> -	 * wait for it to complete in the slowpath
> -	 *
> -	 * FIXME bigjoiner fastpath would be good
> -	 */
> -	if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
> -	    crtc_state->update_pipe || crtc_state->bigjoiner)
> -		goto slow;
> -
> -	/*
> -	 * Don't do an async update if there is an outstanding commit modifying
> -	 * the plane.  This prevents our async update's changes from getting
> -	 * overridden by a previous synchronous update's state.
> -	 */
> -	if (old_plane_state->uapi.commit &&
> -	    !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
> -		goto slow;
> -
> -	/*
> -	 * If any parameters change that may affect watermarks,
> -	 * take the slowpath. Only changing fb or position should be
> -	 * in the fastpath.
> -	 */
> -	if (old_plane_state->uapi.crtc != &crtc->base ||
> -	    old_plane_state->uapi.src_w != src_w ||
> -	    old_plane_state->uapi.src_h != src_h ||
> -	    old_plane_state->uapi.crtc_w != crtc_w ||
> -	    old_plane_state->uapi.crtc_h != crtc_h ||
> -	    !old_plane_state->uapi.fb != !fb)
> -		goto slow;
> -
> -	new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
> -	if (!new_plane_state)
> -		return -ENOMEM;
> -
> -	new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
> -	if (!new_crtc_state) {
> -		ret = -ENOMEM;
> -		goto out_free;
> -	}
> -
> -	drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
> -
> -	new_plane_state->uapi.src_x = src_x;
> -	new_plane_state->uapi.src_y = src_y;
> -	new_plane_state->uapi.src_w = src_w;
> -	new_plane_state->uapi.src_h = src_h;
> -	new_plane_state->uapi.crtc_x = crtc_x;
> -	new_plane_state->uapi.crtc_y = crtc_y;
> -	new_plane_state->uapi.crtc_w = crtc_w;
> -	new_plane_state->uapi.crtc_h = crtc_h;
> -
> -	intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
> -
> -	ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
> -						  old_plane_state, new_plane_state);
> -	if (ret)
> -		goto out_free;
> -
> -	ret = intel_plane_pin_fb(new_plane_state);
> -	if (ret)
> -		goto out_free;
> -
> -	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
> -				ORIGIN_FLIP);
> -	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
> -				to_intel_frontbuffer(new_plane_state->hw.fb),
> -				plane->frontbuffer_bit);
> -
> -	/* Swap plane state */
> -	plane->base.state = &new_plane_state->uapi;
> -
> -	/*
> -	 * We cannot swap crtc_state as it may be in use by an atomic commit or
> -	 * page flip that's running simultaneously. If we swap crtc_state and
> -	 * destroy the old state, we will cause a use-after-free there.
> -	 *
> -	 * Only update active_planes, which is needed for our internal
> -	 * bookkeeping. Either value will do the right thing when updating
> -	 * planes atomically. If the cursor was part of the atomic update then
> -	 * we would have taken the slowpath.
> -	 */
> -	crtc_state->active_planes = new_crtc_state->active_planes;
> -
> -	if (new_plane_state->uapi.visible)
> -		intel_update_plane(plane, crtc_state, new_plane_state);
> -	else
> -		intel_disable_plane(plane, crtc_state);
> -
> -	intel_plane_unpin_fb(old_plane_state);
> -
> -out_free:
> -	if (new_crtc_state)
> -		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
> -	if (ret)
> -		intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
> -	else
> -		intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
> -	return ret;
> -
> -slow:
> -	return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
> -					      crtc_x, crtc_y, crtc_w, crtc_h,
> -					      src_x, src_y, src_w, src_h, ctx);
> -}
> -
> -static const struct drm_plane_funcs intel_cursor_plane_funcs = {
> -	.update_plane = intel_legacy_cursor_update,
> -	.disable_plane = drm_atomic_helper_disable_plane,
> -	.destroy = intel_plane_destroy,
> -	.atomic_duplicate_state = intel_plane_duplicate_state,
> -	.atomic_destroy_state = intel_plane_destroy_state,
> -	.format_mod_supported = intel_cursor_format_mod_supported,
> -};
> -
>  static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
>  			       enum i9xx_plane_id i9xx_plane)
>  {
> @@ -17187,74 +16471,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  	return ERR_PTR(ret);
>  }
>  
> -static struct intel_plane *
> -intel_cursor_plane_create(struct drm_i915_private *dev_priv,
> -			  enum pipe pipe)
> -{
> -	struct intel_plane *cursor;
> -	int ret, zpos;
> -
> -	cursor = intel_plane_alloc();
> -	if (IS_ERR(cursor))
> -		return cursor;
> -
> -	cursor->pipe = pipe;
> -	cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
> -	cursor->id = PLANE_CURSOR;
> -	cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
> -
> -	if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
> -		cursor->max_stride = i845_cursor_max_stride;
> -		cursor->update_plane = i845_update_cursor;
> -		cursor->disable_plane = i845_disable_cursor;
> -		cursor->get_hw_state = i845_cursor_get_hw_state;
> -		cursor->check_plane = i845_check_cursor;
> -	} else {
> -		cursor->max_stride = i9xx_cursor_max_stride;
> -		cursor->update_plane = i9xx_update_cursor;
> -		cursor->disable_plane = i9xx_disable_cursor;
> -		cursor->get_hw_state = i9xx_cursor_get_hw_state;
> -		cursor->check_plane = i9xx_check_cursor;
> -	}
> -
> -	cursor->cursor.base = ~0;
> -	cursor->cursor.cntl = ~0;
> -
> -	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
> -		cursor->cursor.size = ~0;
> -
> -	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
> -				       0, &intel_cursor_plane_funcs,
> -				       intel_cursor_formats,
> -				       ARRAY_SIZE(intel_cursor_formats),
> -				       cursor_format_modifiers,
> -				       DRM_PLANE_TYPE_CURSOR,
> -				       "cursor %c", pipe_name(pipe));
> -	if (ret)
> -		goto fail;
> -
> -	if (INTEL_GEN(dev_priv) >= 4)
> -		drm_plane_create_rotation_property(&cursor->base,
> -						   DRM_MODE_ROTATE_0,
> -						   DRM_MODE_ROTATE_0 |
> -						   DRM_MODE_ROTATE_180);
> -
> -	zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
> -	drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
> -
> -	if (INTEL_GEN(dev_priv) >= 12)
> -		drm_plane_enable_fb_damage_clips(&cursor->base);
> -
> -	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
> -
> -	return cursor;
> -
> -fail:
> -	intel_plane_free(cursor);
> -
> -	return ERR_PTR(ret);
> -}
> -
>  static int intel_crtc_late_register(struct drm_crtc *crtc)
>  {
>  	intel_crtc_debugfs_add(crtc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index a5771bfecba6..f0a5bf69656f 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -647,6 +647,18 @@ bool
>  intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
>  				    uint64_t modifier);
>  
> +int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
> +u32 intel_plane_compute_aligned_offset(int *x, int *y,
> +				       const struct intel_plane_state *state,
> +				       int color_plane);
> +int intel_plane_pin_fb(struct intel_plane_state *plane_state);
> +void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
> +
> +/* cursor */
> +struct intel_plane *
> +intel_cursor_plane_create(struct drm_i915_private *dev_priv,
> +			  enum pipe pipe);
> +
>  /* modesetting */
>  void intel_modeset_init_hw(struct drm_i915_private *i915);
>  int intel_modeset_init_noirq(struct drm_i915_private *i915);
> -- 
> 2.27.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 1/9] drm/i915/display: move needs_modeset to an inline in header
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 1/9] drm/i915/display: move needs_modeset to an inline in header Dave Airlie
@ 2020-12-10 15:08   ` Ville Syrjälä
  0 siblings, 0 replies; 25+ messages in thread
From: Ville Syrjälä @ 2020-12-10 15:08 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 02:17:47PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> This function is going to be used in a later change, so clean it
> up first before moving it.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  | 78 +++++++++----------
>  .../drm/i915/display/intel_display_types.h    |  6 ++
>  2 files changed, 42 insertions(+), 42 deletions(-)
> 
<snip>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 5bc5bfbc4551..8c4afad68a44 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1777,6 +1777,12 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
>  		 (1 << INTEL_OUTPUT_EDP));
>  }
>  
> +static inline bool
> +intel_crtc_needs_modeset(const struct intel_crtc_state *state)

s/state/crtc_state/ please.

With that
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +{
> +	return drm_atomic_crtc_needs_modeset(&state->uapi);
> +}
> +
>  static inline void
>  intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
>  {
> -- 
> 2.27.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 2/9] drm/i915/display: move to_intel_frontbuffer to header
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 2/9] drm/i915/display: move to_intel_frontbuffer to header Dave Airlie
@ 2020-12-10 15:08   ` Ville Syrjälä
  0 siblings, 0 replies; 25+ messages in thread
From: Ville Syrjälä @ 2020-12-10 15:08 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 02:17:48PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> This will be used for some refactoring in other files, so move it
> first.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_display.c       | 6 ------
>  drivers/gpu/drm/i915/display/intel_display_types.h | 6 ++++++
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 80103211f407..62e22d832cab 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -3611,12 +3611,6 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
>  	intel_disable_plane(plane, crtc_state);
>  }
>  
> -static struct intel_frontbuffer *
> -to_intel_frontbuffer(struct drm_framebuffer *fb)
> -{
> -	return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
> -}
> -
>  static void
>  intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
>  			     struct intel_initial_plane_config *plane_config)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 8c4afad68a44..dfe573c8b5ae 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1805,4 +1805,10 @@ static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
>  	return i915_ggtt_offset(state->vma);
>  }
>  
> +static inline struct intel_frontbuffer *
> +to_intel_frontbuffer(struct drm_framebuffer *fb)
> +{
> +	return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
> +}
> +
>  #endif /*  __INTEL_DISPLAY_TYPES_H__ */
> -- 
> 2.27.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 3/9] drm/i915/display: fix misused comma
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 3/9] drm/i915/display: fix misused comma Dave Airlie
@ 2020-12-10 15:09   ` Ville Syrjälä
  0 siblings, 0 replies; 25+ messages in thread
From: Ville Syrjälä @ 2020-12-10 15:09 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 02:17:49PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> There is no need for a comma use here.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 62e22d832cab..79d7479beed2 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -989,7 +989,8 @@ chv_find_best_dpll(const struct intel_limit *limit,
>  	 * set to 2.  If requires to support 200Mhz refclk, we need to
>  	 * revisit this because n may not 1 anymore.
>  	 */
> -	clock.n = 1, clock.m1 = 2;
> +	clock.n = 1;
> +	clock.m1 = 2;
>  	target *= 5;	/* fast clock */
>  
>  	for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
> -- 
> 2.27.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 5/9] drm/i915: refactor some crtc code out of intel display.
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 5/9] drm/i915: refactor some crtc code out of intel display Dave Airlie
@ 2020-12-10 15:13   ` Ville Syrjälä
  0 siblings, 0 replies; 25+ messages in thread
From: Ville Syrjälä @ 2020-12-10 15:13 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 02:17:51PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> There may be more crtc code that can be pulled out, but this
> is a good start.
a> 
> RFC: maybe call the new file something different

Most of that seems to be the primary plane code.

What I would so is:
* i9xx_plane.c for all pre-skl plane code
* skl_universal_plane.c for the skl+ plane code
* non-platform specific plane code probably should go
  to intel_atomic_plane.c which could perhaps use
  a rename to just intel_plane.c

> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
>  drivers/gpu/drm/i915/Makefile                |   1 +
>  drivers/gpu/drm/i915/display/intel_crtc.c    | 951 +++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_display.c | 932 ------------------
>  drivers/gpu/drm/i915/display/intel_display.h |   7 +
>  4 files changed, 959 insertions(+), 932 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_crtc.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 98a35b939052..ffec257702af 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -196,6 +196,7 @@ i915-y += \
>  	display/intel_color.o \
>  	display/intel_combo_phy.o \
>  	display/intel_connector.o \
> +	display/intel_crtc.o \
>  	display/intel_csr.o \
>  	display/intel_cursor.o \
>  	display/intel_display.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> new file mode 100644
> index 000000000000..75a79f18cee2
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> @@ -0,0 +1,951 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_plane.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "intel_atomic.h"
> +#include "intel_atomic_plane.h"
> +#include "intel_color.h"
> +#include "intel_display_debugfs.h"
> +#include "intel_display_types.h"
> +#include "intel_pipe_crc.h"
> +#include "intel_sprite.h"
> +
> +/* Primary plane formats for gen <= 3 */
> +static const u32 i8xx_primary_formats[] = {
> +	DRM_FORMAT_C8,
> +	DRM_FORMAT_XRGB1555,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_XRGB8888,
> +};
> +
> +/* Primary plane formats for ivb (no fp16 due to hw issue) */
> +static const u32 ivb_primary_formats[] = {
> +	DRM_FORMAT_C8,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_XBGR8888,
> +	DRM_FORMAT_XRGB2101010,
> +	DRM_FORMAT_XBGR2101010,
> +};
> +
> +/* Primary plane formats for gen >= 4, except ivb */
> +static const u32 i965_primary_formats[] = {
> +	DRM_FORMAT_C8,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_XBGR8888,
> +	DRM_FORMAT_XRGB2101010,
> +	DRM_FORMAT_XBGR2101010,
> +	DRM_FORMAT_XBGR16161616F,
> +};
> +
> +/* Primary plane formats for vlv/chv */
> +static const u32 vlv_primary_formats[] = {
> +	DRM_FORMAT_C8,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_XBGR8888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ABGR8888,
> +	DRM_FORMAT_XRGB2101010,
> +	DRM_FORMAT_XBGR2101010,
> +	DRM_FORMAT_ARGB2101010,
> +	DRM_FORMAT_ABGR2101010,
> +	DRM_FORMAT_XBGR16161616F,
> +};
> +
> +static const u64 i9xx_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_LINEAR,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
> +static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
> +					    u32 format, u64 modifier)
> +{
> +	switch (modifier) {
> +	case DRM_FORMAT_MOD_LINEAR:
> +	case I915_FORMAT_MOD_X_TILED:
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB1555:
> +	case DRM_FORMAT_XRGB8888:
> +		return modifier == DRM_FORMAT_MOD_LINEAR ||
> +			modifier == I915_FORMAT_MOD_X_TILED;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
> +					    u32 format, u64 modifier)
> +{
> +	switch (modifier) {
> +	case DRM_FORMAT_MOD_LINEAR:
> +	case I915_FORMAT_MOD_X_TILED:
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB8888:
> +	case DRM_FORMAT_XBGR8888:
> +	case DRM_FORMAT_ARGB8888:
> +	case DRM_FORMAT_ABGR8888:
> +	case DRM_FORMAT_XRGB2101010:
> +	case DRM_FORMAT_XBGR2101010:
> +	case DRM_FORMAT_ARGB2101010:
> +	case DRM_FORMAT_ABGR2101010:
> +	case DRM_FORMAT_XBGR16161616F:
> +		return modifier == DRM_FORMAT_MOD_LINEAR ||
> +			modifier == I915_FORMAT_MOD_X_TILED;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
> +			       enum i9xx_plane_id i9xx_plane)
> +{
> +	if (!HAS_FBC(dev_priv))
> +		return false;
> +
> +	if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> +		return i9xx_plane == PLANE_A; /* tied to pipe A */
> +	else if (IS_IVYBRIDGE(dev_priv))
> +		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
> +			i9xx_plane == PLANE_C;
> +	else if (INTEL_GEN(dev_priv) >= 4)
> +		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
> +	else
> +		return i9xx_plane == PLANE_A;
> +}
> +
> +static void assert_vblank_disabled(struct drm_crtc *crtc)
> +{
> +	if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
> +		drm_crtc_vblank_put(crtc);
> +}
> +
> +u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
> +
> +	if (!vblank->max_vblank_count)
> +		return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
> +
> +	return crtc->base.funcs->get_vblank_counter(&crtc->base);
> +}
> +
> +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	u32 mode_flags = crtc->mode_flags;
> +
> +	/*
> +	 * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
> +	 * have updated at the beginning of TE, if we want to use
> +	 * the hw counter, then we would find it updated in only
> +	 * the next TE, hence switching to sw counter.
> +	 */
> +	if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
> +		return 0;
> +
> +	/*
> +	 * On i965gm the hardware frame counter reads
> +	 * zero when the TV encoder is enabled :(
> +	 */
> +	if (IS_I965GM(dev_priv) &&
> +	    (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
> +		return 0;
> +
> +	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> +		return 0xffffffff; /* full 32 bit counter */
> +	else if (INTEL_GEN(dev_priv) >= 3)
> +		return 0xffffff; /* only 24 bits of frame count */
> +	else
> +		return 0; /* Gen2 doesn't have a hardware frame counter */
> +}
> +
> +void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> +	assert_vblank_disabled(&crtc->base);
> +	drm_crtc_set_max_vblank_count(&crtc->base,
> +				      intel_crtc_max_vblank_count(crtc_state));
> +	drm_crtc_vblank_on(&crtc->base);
> +}
> +
> +void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> +	drm_crtc_vblank_off(&crtc->base);
> +	assert_vblank_disabled(&crtc->base);
> +}
> +
> +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
> +{
> +	struct intel_crtc_state *crtc_state;
> +
> +	crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
> +
> +	if (crtc_state)
> +		intel_crtc_state_reset(crtc_state, crtc);
> +
> +	return crtc_state;
> +}
> +
> +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> +			    struct intel_crtc *crtc)
> +{
> +	memset(crtc_state, 0, sizeof(*crtc_state));
> +
> +	__drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
> +
> +	crtc_state->cpu_transcoder = INVALID_TRANSCODER;
> +	crtc_state->master_transcoder = INVALID_TRANSCODER;
> +	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
> +	crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
> +	crtc_state->scaler_state.scaler_id = -1;
> +	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> +}
> +
> +static bool i9xx_plane_has_windowing(struct intel_plane *plane)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +
> +	if (IS_CHERRYVIEW(dev_priv))
> +		return i9xx_plane == PLANE_B;
> +	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> +		return false;
> +	else if (IS_GEN(dev_priv, 4))
> +		return i9xx_plane == PLANE_C;
> +	else
> +		return i9xx_plane == PLANE_B ||
> +			i9xx_plane == PLANE_C;
> +}
> +
> +static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
> +			  const struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv =
> +		to_i915(plane_state->uapi.plane->dev);
> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
> +	unsigned int rotation = plane_state->hw.rotation;
> +	u32 dspcntr;
> +
> +	dspcntr = DISPLAY_PLANE_ENABLE;
> +
> +	if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
> +	    IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> +		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> +
> +	switch (fb->format->format) {
> +	case DRM_FORMAT_C8:
> +		dspcntr |= DISPPLANE_8BPP;
> +		break;
> +	case DRM_FORMAT_XRGB1555:
> +		dspcntr |= DISPPLANE_BGRX555;
> +		break;
> +	case DRM_FORMAT_ARGB1555:
> +		dspcntr |= DISPPLANE_BGRA555;
> +		break;
> +	case DRM_FORMAT_RGB565:
> +		dspcntr |= DISPPLANE_BGRX565;
> +		break;
> +	case DRM_FORMAT_XRGB8888:
> +		dspcntr |= DISPPLANE_BGRX888;
> +		break;
> +	case DRM_FORMAT_XBGR8888:
> +		dspcntr |= DISPPLANE_RGBX888;
> +		break;
> +	case DRM_FORMAT_ARGB8888:
> +		dspcntr |= DISPPLANE_BGRA888;
> +		break;
> +	case DRM_FORMAT_ABGR8888:
> +		dspcntr |= DISPPLANE_RGBA888;
> +		break;
> +	case DRM_FORMAT_XRGB2101010:
> +		dspcntr |= DISPPLANE_BGRX101010;
> +		break;
> +	case DRM_FORMAT_XBGR2101010:
> +		dspcntr |= DISPPLANE_RGBX101010;
> +		break;
> +	case DRM_FORMAT_ARGB2101010:
> +		dspcntr |= DISPPLANE_BGRA101010;
> +		break;
> +	case DRM_FORMAT_ABGR2101010:
> +		dspcntr |= DISPPLANE_RGBA101010;
> +		break;
> +	case DRM_FORMAT_XBGR16161616F:
> +		dspcntr |= DISPPLANE_RGBX161616;
> +		break;
> +	default:
> +		MISSING_CASE(fb->format->format);
> +		return 0;
> +	}
> +
> +	if (INTEL_GEN(dev_priv) >= 4 &&
> +	    fb->modifier == I915_FORMAT_MOD_X_TILED)
> +		dspcntr |= DISPPLANE_TILED;
> +
> +	if (rotation & DRM_MODE_ROTATE_180)
> +		dspcntr |= DISPPLANE_ROTATE_180;
> +
> +	if (rotation & DRM_MODE_REFLECT_X)
> +		dspcntr |= DISPPLANE_MIRROR;
> +
> +	return dspcntr;
> +}
> +
> +static int
> +i9xx_plane_check(struct intel_crtc_state *crtc_state,
> +		 struct intel_plane_state *plane_state)
> +{
> +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> +	int ret;
> +
> +	ret = chv_plane_check_rotation(plane_state);
> +	if (ret)
> +		return ret;
> +
> +	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> +						DRM_PLANE_HELPER_NO_SCALING,
> +						DRM_PLANE_HELPER_NO_SCALING,
> +						i9xx_plane_has_windowing(plane));
> +	if (ret)
> +		return ret;
> +
> +	ret = i9xx_check_plane_surface(plane_state);
> +	if (ret)
> +		return ret;
> +
> +	if (!plane_state->uapi.visible)
> +		return 0;
> +
> +	ret = intel_plane_check_src_coordinates(plane_state);
> +	if (ret)
> +		return ret;
> +
> +	plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
> +
> +	return 0;
> +}
> +
> +static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	u32 dspcntr = 0;
> +
> +	if (crtc_state->gamma_enable)
> +		dspcntr |= DISPPLANE_GAMMA_ENABLE;
> +
> +	if (crtc_state->csc_enable)
> +		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
> +
> +	if (INTEL_GEN(dev_priv) < 5)
> +		dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
> +
> +	return dspcntr;
> +}
> +
> +static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
> +			     const struct intel_plane_state *plane_state,
> +			     unsigned int *num, unsigned int *den)
> +{
> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
> +	unsigned int cpp = fb->format->cpp[0];
> +
> +	/*
> +	 * g4x bspec says 64bpp pixel rate can't exceed 80%
> +	 * of cdclk when the sprite plane is enabled on the
> +	 * same pipe. ilk/snb bspec says 64bpp pixel rate is
> +	 * never allowed to exceed 80% of cdclk. Let's just go
> +	 * with the ilk/snb limit always.
> +	 */
> +	if (cpp == 8) {
> +		*num = 10;
> +		*den = 8;
> +	} else {
> +		*num = 1;
> +		*den = 1;
> +	}
> +}
> +
> +static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
> +				const struct intel_plane_state *plane_state)
> +{
> +	unsigned int pixel_rate;
> +	unsigned int num, den;
> +
> +	/*
> +	 * Note that crtc_state->pixel_rate accounts for both
> +	 * horizontal and vertical panel fitter downscaling factors.
> +	 * Pre-HSW bspec tells us to only consider the horizontal
> +	 * downscaling factor here. We ignore that and just consider
> +	 * both for simplicity.
> +	 */
> +	pixel_rate = crtc_state->pixel_rate;
> +
> +	i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
> +
> +	/* two pixels per clock with double wide pipe */
> +	if (crtc_state->double_wide)
> +		den *= 2;
> +
> +	return DIV_ROUND_UP(pixel_rate * num, den);
> +}
> +
> +static void i9xx_update_plane(struct intel_plane *plane,
> +			      const struct intel_crtc_state *crtc_state,
> +			      const struct intel_plane_state *plane_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +	u32 linear_offset;
> +	int x = plane_state->color_plane[0].x;
> +	int y = plane_state->color_plane[0].y;
> +	int crtc_x = plane_state->uapi.dst.x1;
> +	int crtc_y = plane_state->uapi.dst.y1;
> +	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
> +	int crtc_h = drm_rect_height(&plane_state->uapi.dst);
> +	unsigned long irqflags;
> +	u32 dspaddr_offset;
> +	u32 dspcntr;
> +
> +	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
> +
> +	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
> +
> +	if (INTEL_GEN(dev_priv) >= 4)
> +		dspaddr_offset = plane_state->color_plane[0].offset;
> +	else
> +		dspaddr_offset = linear_offset;
> +
> +	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> +	intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
> +			  plane_state->color_plane[0].stride);
> +
> +	if (INTEL_GEN(dev_priv) < 4) {
> +		/*
> +		 * PLANE_A doesn't actually have a full window
> +		 * generator but let's assume we still need to
> +		 * program whatever is there.
> +		 */
> +		intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
> +				  (crtc_y << 16) | crtc_x);
> +		intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
> +				  ((crtc_h - 1) << 16) | (crtc_w - 1));
> +	} else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
> +		intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
> +				  (crtc_y << 16) | crtc_x);
> +		intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
> +				  ((crtc_h - 1) << 16) | (crtc_w - 1));
> +		intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
> +	}
> +
> +	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
> +		intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
> +				  (y << 16) | x);
> +	} else if (INTEL_GEN(dev_priv) >= 4) {
> +		intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
> +				  linear_offset);
> +		intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
> +				  (y << 16) | x);
> +	}
> +
> +	/*
> +	 * The control register self-arms if the plane was previously
> +	 * disabled. Try to make the plane enable atomic by writing
> +	 * the control register just before the surface register.
> +	 */
> +	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> +	if (INTEL_GEN(dev_priv) >= 4)
> +		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
> +				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> +	else
> +		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
> +				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> +
> +	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static void i9xx_disable_plane(struct intel_plane *plane,
> +			       const struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +	unsigned long irqflags;
> +	u32 dspcntr;
> +
> +	/*
> +	 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
> +	 * enable on ilk+ affect the pipe bottom color as
> +	 * well, so we must configure them even if the plane
> +	 * is disabled.
> +	 *
> +	 * On pre-g4x there is no way to gamma correct the
> +	 * pipe bottom color but we'll keep on doing this
> +	 * anyway so that the crtc state readout works correctly.
> +	 */
> +	dspcntr = i9xx_plane_ctl_crtc(crtc_state);
> +
> +	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> +	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> +	if (INTEL_GEN(dev_priv) >= 4)
> +		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
> +	else
> +		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
> +
> +	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
> +				    enum pipe *pipe)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +	enum intel_display_power_domain power_domain;
> +	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +	intel_wakeref_t wakeref;
> +	bool ret;
> +	u32 val;
> +
> +	/*
> +	 * Not 100% correct for planes that can move between pipes,
> +	 * but that's only the case for gen2-4 which don't have any
> +	 * display power wells.
> +	 */
> +	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
> +		return false;
> +
> +	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
> +
> +	ret = val & DISPLAY_PLANE_ENABLE;
> +
> +	if (INTEL_GEN(dev_priv) >= 5)
> +		*pipe = plane->pipe;
> +	else
> +		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
> +			DISPPLANE_SEL_PIPE_SHIFT;
> +
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
> +
> +	return ret;
> +}
> +
> +unsigned int
> +i9xx_plane_max_stride(struct intel_plane *plane,
> +		      u32 pixel_format, u64 modifier,
> +		      unsigned int rotation)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +
> +	if (!HAS_GMCH(dev_priv)) {
> +		return 32*1024;
> +	} else if (INTEL_GEN(dev_priv) >= 4) {
> +		if (modifier == I915_FORMAT_MOD_X_TILED)
> +			return 16*1024;
> +		else
> +			return 32*1024;
> +	} else if (INTEL_GEN(dev_priv) >= 3) {
> +		if (modifier == I915_FORMAT_MOD_X_TILED)
> +			return 8*1024;
> +		else
> +			return 16*1024;
> +	} else {
> +		if (plane->i9xx_plane == PLANE_C)
> +			return 4*1024;
> +		else
> +			return 8*1024;
> +	}
> +}
> +
> +static const struct drm_plane_funcs i965_plane_funcs = {
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
> +	.destroy = intel_plane_destroy,
> +	.atomic_duplicate_state = intel_plane_duplicate_state,
> +	.atomic_destroy_state = intel_plane_destroy_state,
> +	.format_mod_supported = i965_plane_format_mod_supported,
> +};
> +
> +static const struct drm_plane_funcs i8xx_plane_funcs = {
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
> +	.destroy = intel_plane_destroy,
> +	.atomic_duplicate_state = intel_plane_duplicate_state,
> +	.atomic_destroy_state = intel_plane_destroy_state,
> +	.format_mod_supported = i8xx_plane_format_mod_supported,
> +};
> +
> +static struct intel_plane *
> +intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> +{
> +	struct intel_plane *plane;
> +	const struct drm_plane_funcs *plane_funcs;
> +	unsigned int supported_rotations;
> +	const u32 *formats;
> +	int num_formats;
> +	int ret, zpos;
> +
> +	if (INTEL_GEN(dev_priv) >= 9)
> +		return skl_universal_plane_create(dev_priv, pipe,
> +						  PLANE_PRIMARY);
> +
> +	plane = intel_plane_alloc();
> +	if (IS_ERR(plane))
> +		return plane;
> +
> +	plane->pipe = pipe;
> +	/*
> +	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
> +	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
> +	 */
> +	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
> +	    INTEL_NUM_PIPES(dev_priv) == 2)
> +		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
> +	else
> +		plane->i9xx_plane = (enum i9xx_plane_id) pipe;
> +	plane->id = PLANE_PRIMARY;
> +	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
> +
> +	plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
> +	if (plane->has_fbc) {
> +		struct intel_fbc *fbc = &dev_priv->fbc;
> +
> +		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
> +	}
> +
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +		formats = vlv_primary_formats;
> +		num_formats = ARRAY_SIZE(vlv_primary_formats);
> +	} else if (INTEL_GEN(dev_priv) >= 4) {
> +		/*
> +		 * WaFP16GammaEnabling:ivb
> +		 * "Workaround : When using the 64-bit format, the plane
> +		 *  output on each color channel has one quarter amplitude.
> +		 *  It can be brought up to full amplitude by using pipe
> +		 *  gamma correction or pipe color space conversion to
> +		 *  multiply the plane output by four."
> +		 *
> +		 * There is no dedicated plane gamma for the primary plane,
> +		 * and using the pipe gamma/csc could conflict with other
> +		 * planes, so we choose not to expose fp16 on IVB primary
> +		 * planes. HSW primary planes no longer have this problem.
> +		 */
> +		if (IS_IVYBRIDGE(dev_priv)) {
> +			formats = ivb_primary_formats;
> +			num_formats = ARRAY_SIZE(ivb_primary_formats);
> +		} else {
> +			formats = i965_primary_formats;
> +			num_formats = ARRAY_SIZE(i965_primary_formats);
> +		}
> +	} else {
> +		formats = i8xx_primary_formats;
> +		num_formats = ARRAY_SIZE(i8xx_primary_formats);
> +	}
> +
> +	if (INTEL_GEN(dev_priv) >= 4)
> +		plane_funcs = &i965_plane_funcs;
> +	else
> +		plane_funcs = &i8xx_plane_funcs;
> +
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		plane->min_cdclk = vlv_plane_min_cdclk;
> +	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> +		plane->min_cdclk = hsw_plane_min_cdclk;
> +	else if (IS_IVYBRIDGE(dev_priv))
> +		plane->min_cdclk = ivb_plane_min_cdclk;
> +	else
> +		plane->min_cdclk = i9xx_plane_min_cdclk;
> +
> +	plane->max_stride = i9xx_plane_max_stride;
> +	plane->update_plane = i9xx_update_plane;
> +	plane->disable_plane = i9xx_disable_plane;
> +	plane->get_hw_state = i9xx_plane_get_hw_state;
> +	plane->check_plane = i9xx_plane_check;
> +
> +	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> +		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> +					       0, plane_funcs,
> +					       formats, num_formats,
> +					       i9xx_format_modifiers,
> +					       DRM_PLANE_TYPE_PRIMARY,
> +					       "primary %c", pipe_name(pipe));
> +	else
> +		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> +					       0, plane_funcs,
> +					       formats, num_formats,
> +					       i9xx_format_modifiers,
> +					       DRM_PLANE_TYPE_PRIMARY,
> +					       "plane %c",
> +					       plane_name(plane->i9xx_plane));
> +	if (ret)
> +		goto fail;
> +
> +	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> +		supported_rotations =
> +			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
> +			DRM_MODE_REFLECT_X;
> +	} else if (INTEL_GEN(dev_priv) >= 4) {
> +		supported_rotations =
> +			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
> +	} else {
> +		supported_rotations = DRM_MODE_ROTATE_0;
> +	}
> +
> +	if (INTEL_GEN(dev_priv) >= 4)
> +		drm_plane_create_rotation_property(&plane->base,
> +						   DRM_MODE_ROTATE_0,
> +						   supported_rotations);
> +
> +	zpos = 0;
> +	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
> +
> +	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
> +
> +	return plane;
> +
> +fail:
> +	intel_plane_free(plane);
> +
> +	return ERR_PTR(ret);
> +}
> +
> +static struct intel_crtc *intel_crtc_alloc(void)
> +{
> +	struct intel_crtc_state *crtc_state;
> +	struct intel_crtc *crtc;
> +
> +	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
> +	if (!crtc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	crtc_state = intel_crtc_state_alloc(crtc);
> +	if (!crtc_state) {
> +		kfree(crtc);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	crtc->base.state = &crtc_state->uapi;
> +	crtc->config = crtc_state;
> +
> +	return crtc;
> +}
> +
> +static void intel_crtc_free(struct intel_crtc *crtc)
> +{
> +	intel_crtc_destroy_state(&crtc->base, crtc->base.state);
> +	kfree(crtc);
> +}
> +
> +static void intel_crtc_destroy(struct drm_crtc *crtc)
> +{
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +
> +	drm_crtc_cleanup(crtc);
> +	kfree(intel_crtc);
> +}
> +
> +static int intel_crtc_late_register(struct drm_crtc *crtc)
> +{
> +	intel_crtc_debugfs_add(crtc);
> +	return 0;
> +}
> +
> +#define INTEL_CRTC_FUNCS \
> +	.gamma_set = drm_atomic_helper_legacy_gamma_set, \
> +	.set_config = drm_atomic_helper_set_config, \
> +	.destroy = intel_crtc_destroy, \
> +	.page_flip = drm_atomic_helper_page_flip, \
> +	.atomic_duplicate_state = intel_crtc_duplicate_state, \
> +	.atomic_destroy_state = intel_crtc_destroy_state, \
> +	.set_crc_source = intel_crtc_set_crc_source, \
> +	.verify_crc_source = intel_crtc_verify_crc_source, \
> +	.get_crc_sources = intel_crtc_get_crc_sources, \
> +	.late_register = intel_crtc_late_register
> +
> +static const struct drm_crtc_funcs bdw_crtc_funcs = {
> +	INTEL_CRTC_FUNCS,
> +
> +	.get_vblank_counter = g4x_get_vblank_counter,
> +	.enable_vblank = bdw_enable_vblank,
> +	.disable_vblank = bdw_disable_vblank,
> +	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs ilk_crtc_funcs = {
> +	INTEL_CRTC_FUNCS,
> +
> +	.get_vblank_counter = g4x_get_vblank_counter,
> +	.enable_vblank = ilk_enable_vblank,
> +	.disable_vblank = ilk_disable_vblank,
> +	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs g4x_crtc_funcs = {
> +	INTEL_CRTC_FUNCS,
> +
> +	.get_vblank_counter = g4x_get_vblank_counter,
> +	.enable_vblank = i965_enable_vblank,
> +	.disable_vblank = i965_disable_vblank,
> +	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i965_crtc_funcs = {
> +	INTEL_CRTC_FUNCS,
> +
> +	.get_vblank_counter = i915_get_vblank_counter,
> +	.enable_vblank = i965_enable_vblank,
> +	.disable_vblank = i965_disable_vblank,
> +	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i915gm_crtc_funcs = {
> +	INTEL_CRTC_FUNCS,
> +
> +	.get_vblank_counter = i915_get_vblank_counter,
> +	.enable_vblank = i915gm_enable_vblank,
> +	.disable_vblank = i915gm_disable_vblank,
> +	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i915_crtc_funcs = {
> +	INTEL_CRTC_FUNCS,
> +
> +	.get_vblank_counter = i915_get_vblank_counter,
> +	.enable_vblank = i8xx_enable_vblank,
> +	.disable_vblank = i8xx_disable_vblank,
> +	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i8xx_crtc_funcs = {
> +	INTEL_CRTC_FUNCS,
> +
> +	/* no hw vblank counter */
> +	.enable_vblank = i8xx_enable_vblank,
> +	.disable_vblank = i8xx_disable_vblank,
> +	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
> +{
> +	struct intel_plane *primary, *cursor;
> +	const struct drm_crtc_funcs *funcs;
> +	struct intel_crtc *crtc;
> +	int sprite, ret;
> +
> +	crtc = intel_crtc_alloc();
> +	if (IS_ERR(crtc))
> +		return PTR_ERR(crtc);
> +
> +	crtc->pipe = pipe;
> +	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
> +
> +	primary = intel_primary_plane_create(dev_priv, pipe);
> +	if (IS_ERR(primary)) {
> +		ret = PTR_ERR(primary);
> +		goto fail;
> +	}
> +	crtc->plane_ids_mask |= BIT(primary->id);
> +
> +	for_each_sprite(dev_priv, pipe, sprite) {
> +		struct intel_plane *plane;
> +
> +		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
> +		if (IS_ERR(plane)) {
> +			ret = PTR_ERR(plane);
> +			goto fail;
> +		}
> +		crtc->plane_ids_mask |= BIT(plane->id);
> +	}
> +
> +	cursor = intel_cursor_plane_create(dev_priv, pipe);
> +	if (IS_ERR(cursor)) {
> +		ret = PTR_ERR(cursor);
> +		goto fail;
> +	}
> +	crtc->plane_ids_mask |= BIT(cursor->id);
> +
> +	if (HAS_GMCH(dev_priv)) {
> +		if (IS_CHERRYVIEW(dev_priv) ||
> +		    IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
> +			funcs = &g4x_crtc_funcs;
> +		else if (IS_GEN(dev_priv, 4))
> +			funcs = &i965_crtc_funcs;
> +		else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
> +			funcs = &i915gm_crtc_funcs;
> +		else if (IS_GEN(dev_priv, 3))
> +			funcs = &i915_crtc_funcs;
> +		else
> +			funcs = &i8xx_crtc_funcs;
> +	} else {
> +		if (INTEL_GEN(dev_priv) >= 8)
> +			funcs = &bdw_crtc_funcs;
> +		else
> +			funcs = &ilk_crtc_funcs;
> +	}
> +
> +	ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
> +					&primary->base, &cursor->base,
> +					funcs, "pipe %c", pipe_name(pipe));
> +	if (ret)
> +		goto fail;
> +
> +	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
> +	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
> +	dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
> +
> +	if (INTEL_GEN(dev_priv) < 9) {
> +		enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
> +
> +		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
> +		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
> +		dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
> +	}
> +
> +	if (INTEL_GEN(dev_priv) >= 10)
> +		drm_crtc_create_scaling_filter_property(&crtc->base,
> +						BIT(DRM_SCALING_FILTER_DEFAULT) |
> +						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
> +
> +	intel_color_init(crtc);
> +
> +	intel_crtc_crc_init(crtc);
> +
> +	drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
> +
> +	return 0;
> +
> +fail:
> +	intel_crtc_free(crtc);
> +
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 722a1cf61941..2507a72ee249 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -87,56 +87,6 @@
>  #include "intel_tc.h"
>  #include "intel_vga.h"
>  
> -/* Primary plane formats for gen <= 3 */
> -static const u32 i8xx_primary_formats[] = {
> -	DRM_FORMAT_C8,
> -	DRM_FORMAT_XRGB1555,
> -	DRM_FORMAT_RGB565,
> -	DRM_FORMAT_XRGB8888,
> -};
> -
> -/* Primary plane formats for ivb (no fp16 due to hw issue) */
> -static const u32 ivb_primary_formats[] = {
> -	DRM_FORMAT_C8,
> -	DRM_FORMAT_RGB565,
> -	DRM_FORMAT_XRGB8888,
> -	DRM_FORMAT_XBGR8888,
> -	DRM_FORMAT_XRGB2101010,
> -	DRM_FORMAT_XBGR2101010,
> -};
> -
> -/* Primary plane formats for gen >= 4, except ivb */
> -static const u32 i965_primary_formats[] = {
> -	DRM_FORMAT_C8,
> -	DRM_FORMAT_RGB565,
> -	DRM_FORMAT_XRGB8888,
> -	DRM_FORMAT_XBGR8888,
> -	DRM_FORMAT_XRGB2101010,
> -	DRM_FORMAT_XBGR2101010,
> -	DRM_FORMAT_XBGR16161616F,
> -};
> -
> -/* Primary plane formats for vlv/chv */
> -static const u32 vlv_primary_formats[] = {
> -	DRM_FORMAT_C8,
> -	DRM_FORMAT_RGB565,
> -	DRM_FORMAT_XRGB8888,
> -	DRM_FORMAT_XBGR8888,
> -	DRM_FORMAT_ARGB8888,
> -	DRM_FORMAT_ABGR8888,
> -	DRM_FORMAT_XRGB2101010,
> -	DRM_FORMAT_XBGR2101010,
> -	DRM_FORMAT_ARGB2101010,
> -	DRM_FORMAT_ABGR2101010,
> -	DRM_FORMAT_XBGR16161616F,
> -};
> -
> -static const u64 i9xx_format_modifiers[] = {
> -	I915_FORMAT_MOD_X_TILED,
> -	DRM_FORMAT_MOD_LINEAR,
> -	DRM_FORMAT_MOD_INVALID
> -};
> -
>  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
>  				struct intel_crtc_state *pipe_config);
>  static void ilk_pch_clock_get(struct intel_crtc *crtc,
> @@ -162,7 +112,6 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state);
>  static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
>  static void intel_modeset_setup_hw_state(struct drm_device *dev,
>  					 struct drm_modeset_acquire_ctx *ctx);
> -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
>  
>  struct intel_limit {
>  	struct {
> @@ -1301,12 +1250,6 @@ static void assert_planes_disabled(struct intel_crtc *crtc)
>  		assert_plane_disabled(plane);
>  }
>  
> -static void assert_vblank_disabled(struct drm_crtc *crtc)
> -{
> -	if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
> -		drm_crtc_vblank_put(crtc);
> -}
> -
>  void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
>  				    enum pipe pipe)
>  {
> @@ -1791,55 +1734,6 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
>  		return crtc->pipe;
>  }
>  
> -static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -	u32 mode_flags = crtc->mode_flags;
> -
> -	/*
> -	 * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
> -	 * have updated at the beginning of TE, if we want to use
> -	 * the hw counter, then we would find it updated in only
> -	 * the next TE, hence switching to sw counter.
> -	 */
> -	if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
> -		return 0;
> -
> -	/*
> -	 * On i965gm the hardware frame counter reads
> -	 * zero when the TV encoder is enabled :(
> -	 */
> -	if (IS_I965GM(dev_priv) &&
> -	    (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
> -		return 0;
> -
> -	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> -		return 0xffffffff; /* full 32 bit counter */
> -	else if (INTEL_GEN(dev_priv) >= 3)
> -		return 0xffffff; /* only 24 bits of frame count */
> -	else
> -		return 0; /* Gen2 doesn't have a hardware frame counter */
> -}
> -
> -void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
> -{
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -
> -	assert_vblank_disabled(&crtc->base);
> -	drm_crtc_set_max_vblank_count(&crtc->base,
> -				      intel_crtc_max_vblank_count(crtc_state));
> -	drm_crtc_vblank_on(&crtc->base);
> -}
> -
> -void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
> -{
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -
> -	drm_crtc_vblank_off(&crtc->base);
> -	assert_vblank_disabled(&crtc->base);
> -}
> -
>  void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
> @@ -4046,171 +3940,6 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
>  	return 0;
>  }
>  
> -static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
> -			     const struct intel_plane_state *plane_state,
> -			     unsigned int *num, unsigned int *den)
> -{
> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
> -	unsigned int cpp = fb->format->cpp[0];
> -
> -	/*
> -	 * g4x bspec says 64bpp pixel rate can't exceed 80%
> -	 * of cdclk when the sprite plane is enabled on the
> -	 * same pipe. ilk/snb bspec says 64bpp pixel rate is
> -	 * never allowed to exceed 80% of cdclk. Let's just go
> -	 * with the ilk/snb limit always.
> -	 */
> -	if (cpp == 8) {
> -		*num = 10;
> -		*den = 8;
> -	} else {
> -		*num = 1;
> -		*den = 1;
> -	}
> -}
> -
> -static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
> -				const struct intel_plane_state *plane_state)
> -{
> -	unsigned int pixel_rate;
> -	unsigned int num, den;
> -
> -	/*
> -	 * Note that crtc_state->pixel_rate accounts for both
> -	 * horizontal and vertical panel fitter downscaling factors.
> -	 * Pre-HSW bspec tells us to only consider the horizontal
> -	 * downscaling factor here. We ignore that and just consider
> -	 * both for simplicity.
> -	 */
> -	pixel_rate = crtc_state->pixel_rate;
> -
> -	i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
> -
> -	/* two pixels per clock with double wide pipe */
> -	if (crtc_state->double_wide)
> -		den *= 2;
> -
> -	return DIV_ROUND_UP(pixel_rate * num, den);
> -}
> -
> -unsigned int
> -i9xx_plane_max_stride(struct intel_plane *plane,
> -		      u32 pixel_format, u64 modifier,
> -		      unsigned int rotation)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -
> -	if (!HAS_GMCH(dev_priv)) {
> -		return 32*1024;
> -	} else if (INTEL_GEN(dev_priv) >= 4) {
> -		if (modifier == I915_FORMAT_MOD_X_TILED)
> -			return 16*1024;
> -		else
> -			return 32*1024;
> -	} else if (INTEL_GEN(dev_priv) >= 3) {
> -		if (modifier == I915_FORMAT_MOD_X_TILED)
> -			return 8*1024;
> -		else
> -			return 16*1024;
> -	} else {
> -		if (plane->i9xx_plane == PLANE_C)
> -			return 4*1024;
> -		else
> -			return 8*1024;
> -	}
> -}
> -
> -static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
> -{
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -	u32 dspcntr = 0;
> -
> -	if (crtc_state->gamma_enable)
> -		dspcntr |= DISPPLANE_GAMMA_ENABLE;
> -
> -	if (crtc_state->csc_enable)
> -		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
> -
> -	if (INTEL_GEN(dev_priv) < 5)
> -		dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
> -
> -	return dspcntr;
> -}
> -
> -static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
> -			  const struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv =
> -		to_i915(plane_state->uapi.plane->dev);
> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
> -	unsigned int rotation = plane_state->hw.rotation;
> -	u32 dspcntr;
> -
> -	dspcntr = DISPLAY_PLANE_ENABLE;
> -
> -	if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
> -	    IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> -		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> -
> -	switch (fb->format->format) {
> -	case DRM_FORMAT_C8:
> -		dspcntr |= DISPPLANE_8BPP;
> -		break;
> -	case DRM_FORMAT_XRGB1555:
> -		dspcntr |= DISPPLANE_BGRX555;
> -		break;
> -	case DRM_FORMAT_ARGB1555:
> -		dspcntr |= DISPPLANE_BGRA555;
> -		break;
> -	case DRM_FORMAT_RGB565:
> -		dspcntr |= DISPPLANE_BGRX565;
> -		break;
> -	case DRM_FORMAT_XRGB8888:
> -		dspcntr |= DISPPLANE_BGRX888;
> -		break;
> -	case DRM_FORMAT_XBGR8888:
> -		dspcntr |= DISPPLANE_RGBX888;
> -		break;
> -	case DRM_FORMAT_ARGB8888:
> -		dspcntr |= DISPPLANE_BGRA888;
> -		break;
> -	case DRM_FORMAT_ABGR8888:
> -		dspcntr |= DISPPLANE_RGBA888;
> -		break;
> -	case DRM_FORMAT_XRGB2101010:
> -		dspcntr |= DISPPLANE_BGRX101010;
> -		break;
> -	case DRM_FORMAT_XBGR2101010:
> -		dspcntr |= DISPPLANE_RGBX101010;
> -		break;
> -	case DRM_FORMAT_ARGB2101010:
> -		dspcntr |= DISPPLANE_BGRA101010;
> -		break;
> -	case DRM_FORMAT_ABGR2101010:
> -		dspcntr |= DISPPLANE_RGBA101010;
> -		break;
> -	case DRM_FORMAT_XBGR16161616F:
> -		dspcntr |= DISPPLANE_RGBX161616;
> -		break;
> -	default:
> -		MISSING_CASE(fb->format->format);
> -		return 0;
> -	}
> -
> -	if (INTEL_GEN(dev_priv) >= 4 &&
> -	    fb->modifier == I915_FORMAT_MOD_X_TILED)
> -		dspcntr |= DISPPLANE_TILED;
> -
> -	if (rotation & DRM_MODE_ROTATE_180)
> -		dspcntr |= DISPPLANE_ROTATE_180;
> -
> -	if (rotation & DRM_MODE_REFLECT_X)
> -		dspcntr |= DISPPLANE_MIRROR;
> -
> -	return dspcntr;
> -}
> -
>  int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
>  {
>  	struct drm_i915_private *dev_priv =
> @@ -4271,197 +4000,6 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
>  	return 0;
>  }
>  
> -static bool i9xx_plane_has_windowing(struct intel_plane *plane)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -
> -	if (IS_CHERRYVIEW(dev_priv))
> -		return i9xx_plane == PLANE_B;
> -	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> -		return false;
> -	else if (IS_GEN(dev_priv, 4))
> -		return i9xx_plane == PLANE_C;
> -	else
> -		return i9xx_plane == PLANE_B ||
> -			i9xx_plane == PLANE_C;
> -}
> -
> -static int
> -i9xx_plane_check(struct intel_crtc_state *crtc_state,
> -		 struct intel_plane_state *plane_state)
> -{
> -	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> -	int ret;
> -
> -	ret = chv_plane_check_rotation(plane_state);
> -	if (ret)
> -		return ret;
> -
> -	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> -						DRM_PLANE_HELPER_NO_SCALING,
> -						DRM_PLANE_HELPER_NO_SCALING,
> -						i9xx_plane_has_windowing(plane));
> -	if (ret)
> -		return ret;
> -
> -	ret = i9xx_check_plane_surface(plane_state);
> -	if (ret)
> -		return ret;
> -
> -	if (!plane_state->uapi.visible)
> -		return 0;
> -
> -	ret = intel_plane_check_src_coordinates(plane_state);
> -	if (ret)
> -		return ret;
> -
> -	plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
> -
> -	return 0;
> -}
> -
> -static void i9xx_update_plane(struct intel_plane *plane,
> -			      const struct intel_crtc_state *crtc_state,
> -			      const struct intel_plane_state *plane_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -	u32 linear_offset;
> -	int x = plane_state->color_plane[0].x;
> -	int y = plane_state->color_plane[0].y;
> -	int crtc_x = plane_state->uapi.dst.x1;
> -	int crtc_y = plane_state->uapi.dst.y1;
> -	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
> -	int crtc_h = drm_rect_height(&plane_state->uapi.dst);
> -	unsigned long irqflags;
> -	u32 dspaddr_offset;
> -	u32 dspcntr;
> -
> -	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
> -
> -	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
> -
> -	if (INTEL_GEN(dev_priv) >= 4)
> -		dspaddr_offset = plane_state->color_plane[0].offset;
> -	else
> -		dspaddr_offset = linear_offset;
> -
> -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> -	intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
> -			  plane_state->color_plane[0].stride);
> -
> -	if (INTEL_GEN(dev_priv) < 4) {
> -		/*
> -		 * PLANE_A doesn't actually have a full window
> -		 * generator but let's assume we still need to
> -		 * program whatever is there.
> -		 */
> -		intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
> -				  (crtc_y << 16) | crtc_x);
> -		intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
> -				  ((crtc_h - 1) << 16) | (crtc_w - 1));
> -	} else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
> -		intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
> -				  (crtc_y << 16) | crtc_x);
> -		intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
> -				  ((crtc_h - 1) << 16) | (crtc_w - 1));
> -		intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
> -	}
> -
> -	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
> -		intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
> -				  (y << 16) | x);
> -	} else if (INTEL_GEN(dev_priv) >= 4) {
> -		intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
> -				  linear_offset);
> -		intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
> -				  (y << 16) | x);
> -	}
> -
> -	/*
> -	 * The control register self-arms if the plane was previously
> -	 * disabled. Try to make the plane enable atomic by writing
> -	 * the control register just before the surface register.
> -	 */
> -	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> -	if (INTEL_GEN(dev_priv) >= 4)
> -		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
> -				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> -	else
> -		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
> -				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> -
> -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static void i9xx_disable_plane(struct intel_plane *plane,
> -			       const struct intel_crtc_state *crtc_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -	unsigned long irqflags;
> -	u32 dspcntr;
> -
> -	/*
> -	 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
> -	 * enable on ilk+ affect the pipe bottom color as
> -	 * well, so we must configure them even if the plane
> -	 * is disabled.
> -	 *
> -	 * On pre-g4x there is no way to gamma correct the
> -	 * pipe bottom color but we'll keep on doing this
> -	 * anyway so that the crtc state readout works correctly.
> -	 */
> -	dspcntr = i9xx_plane_ctl_crtc(crtc_state);
> -
> -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> -	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> -	if (INTEL_GEN(dev_priv) >= 4)
> -		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
> -	else
> -		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
> -
> -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
> -				    enum pipe *pipe)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	enum intel_display_power_domain power_domain;
> -	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -	intel_wakeref_t wakeref;
> -	bool ret;
> -	u32 val;
> -
> -	/*
> -	 * Not 100% correct for planes that can move between pipes,
> -	 * but that's only the case for gen2-4 which don't have any
> -	 * display power wells.
> -	 */
> -	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> -	if (!wakeref)
> -		return false;
> -
> -	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
> -
> -	ret = val & DISPLAY_PLANE_ENABLE;
> -
> -	if (INTEL_GEN(dev_priv) >= 5)
> -		*pipe = plane->pipe;
> -	else
> -		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
> -			DISPPLANE_SEL_PIPE_SHIFT;
> -
> -	intel_display_power_put(dev_priv, power_domain, wakeref);
> -
> -	return ret;
> -}
> -
>  static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
>  {
>  	struct drm_device *dev = intel_crtc->base.dev;
> @@ -11908,33 +11446,6 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc,
>  					 &pipe_config->fdi_m_n);
>  }
>  
> -static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> -				   struct intel_crtc *crtc)
> -{
> -	memset(crtc_state, 0, sizeof(*crtc_state));
> -
> -	__drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
> -
> -	crtc_state->cpu_transcoder = INVALID_TRANSCODER;
> -	crtc_state->master_transcoder = INVALID_TRANSCODER;
> -	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
> -	crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
> -	crtc_state->scaler_state.scaler_id = -1;
> -	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> -}
> -
> -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
> -{
> -	struct intel_crtc_state *crtc_state;
> -
> -	crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
> -
> -	if (crtc_state)
> -		intel_crtc_state_reset(crtc_state, crtc);
> -
> -	return crtc_state;
> -}
> -
>  /* Returns the currently programmed mode of the given encoder. */
>  struct drm_display_mode *
>  intel_encoder_current_mode(struct intel_encoder *encoder)
> @@ -11975,14 +11486,6 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
>  	return mode;
>  }
>  
> -static void intel_crtc_destroy(struct drm_crtc *crtc)
> -{
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -
> -	drm_crtc_cleanup(crtc);
> -	kfree(intel_crtc);
> -}
> -
>  /**
>   * intel_wm_need_update - Check whether watermarks need updating
>   * @cur: current plane state
> @@ -15186,17 +14689,6 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
>  	return 0;
>  }
>  
> -u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
> -{
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
> -
> -	if (!vblank->max_vblank_count)
> -		return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
> -
> -	return crtc->base.funcs->get_vblank_counter(&crtc->base);
> -}
> -
>  void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
>  				  struct intel_crtc_state *crtc_state)
>  {
> @@ -16249,336 +15741,6 @@ void intel_plane_destroy(struct drm_plane *plane)
>  	kfree(to_intel_plane(plane));
>  }
>  
> -static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
> -					    u32 format, u64 modifier)
> -{
> -	switch (modifier) {
> -	case DRM_FORMAT_MOD_LINEAR:
> -	case I915_FORMAT_MOD_X_TILED:
> -		break;
> -	default:
> -		return false;
> -	}
> -
> -	switch (format) {
> -	case DRM_FORMAT_C8:
> -	case DRM_FORMAT_RGB565:
> -	case DRM_FORMAT_XRGB1555:
> -	case DRM_FORMAT_XRGB8888:
> -		return modifier == DRM_FORMAT_MOD_LINEAR ||
> -			modifier == I915_FORMAT_MOD_X_TILED;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
> -					    u32 format, u64 modifier)
> -{
> -	switch (modifier) {
> -	case DRM_FORMAT_MOD_LINEAR:
> -	case I915_FORMAT_MOD_X_TILED:
> -		break;
> -	default:
> -		return false;
> -	}
> -
> -	switch (format) {
> -	case DRM_FORMAT_C8:
> -	case DRM_FORMAT_RGB565:
> -	case DRM_FORMAT_XRGB8888:
> -	case DRM_FORMAT_XBGR8888:
> -	case DRM_FORMAT_ARGB8888:
> -	case DRM_FORMAT_ABGR8888:
> -	case DRM_FORMAT_XRGB2101010:
> -	case DRM_FORMAT_XBGR2101010:
> -	case DRM_FORMAT_ARGB2101010:
> -	case DRM_FORMAT_ABGR2101010:
> -	case DRM_FORMAT_XBGR16161616F:
> -		return modifier == DRM_FORMAT_MOD_LINEAR ||
> -			modifier == I915_FORMAT_MOD_X_TILED;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static const struct drm_plane_funcs i965_plane_funcs = {
> -	.update_plane = drm_atomic_helper_update_plane,
> -	.disable_plane = drm_atomic_helper_disable_plane,
> -	.destroy = intel_plane_destroy,
> -	.atomic_duplicate_state = intel_plane_duplicate_state,
> -	.atomic_destroy_state = intel_plane_destroy_state,
> -	.format_mod_supported = i965_plane_format_mod_supported,
> -};
> -
> -static const struct drm_plane_funcs i8xx_plane_funcs = {
> -	.update_plane = drm_atomic_helper_update_plane,
> -	.disable_plane = drm_atomic_helper_disable_plane,
> -	.destroy = intel_plane_destroy,
> -	.atomic_duplicate_state = intel_plane_duplicate_state,
> -	.atomic_destroy_state = intel_plane_destroy_state,
> -	.format_mod_supported = i8xx_plane_format_mod_supported,
> -};
> -
> -static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
> -			       enum i9xx_plane_id i9xx_plane)
> -{
> -	if (!HAS_FBC(dev_priv))
> -		return false;
> -
> -	if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> -		return i9xx_plane == PLANE_A; /* tied to pipe A */
> -	else if (IS_IVYBRIDGE(dev_priv))
> -		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
> -			i9xx_plane == PLANE_C;
> -	else if (INTEL_GEN(dev_priv) >= 4)
> -		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
> -	else
> -		return i9xx_plane == PLANE_A;
> -}
> -
> -static struct intel_plane *
> -intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> -{
> -	struct intel_plane *plane;
> -	const struct drm_plane_funcs *plane_funcs;
> -	unsigned int supported_rotations;
> -	const u32 *formats;
> -	int num_formats;
> -	int ret, zpos;
> -
> -	if (INTEL_GEN(dev_priv) >= 9)
> -		return skl_universal_plane_create(dev_priv, pipe,
> -						  PLANE_PRIMARY);
> -
> -	plane = intel_plane_alloc();
> -	if (IS_ERR(plane))
> -		return plane;
> -
> -	plane->pipe = pipe;
> -	/*
> -	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
> -	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
> -	 */
> -	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
> -	    INTEL_NUM_PIPES(dev_priv) == 2)
> -		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
> -	else
> -		plane->i9xx_plane = (enum i9xx_plane_id) pipe;
> -	plane->id = PLANE_PRIMARY;
> -	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
> -
> -	plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
> -	if (plane->has_fbc) {
> -		struct intel_fbc *fbc = &dev_priv->fbc;
> -
> -		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
> -	}
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		formats = vlv_primary_formats;
> -		num_formats = ARRAY_SIZE(vlv_primary_formats);
> -	} else if (INTEL_GEN(dev_priv) >= 4) {
> -		/*
> -		 * WaFP16GammaEnabling:ivb
> -		 * "Workaround : When using the 64-bit format, the plane
> -		 *  output on each color channel has one quarter amplitude.
> -		 *  It can be brought up to full amplitude by using pipe
> -		 *  gamma correction or pipe color space conversion to
> -		 *  multiply the plane output by four."
> -		 *
> -		 * There is no dedicated plane gamma for the primary plane,
> -		 * and using the pipe gamma/csc could conflict with other
> -		 * planes, so we choose not to expose fp16 on IVB primary
> -		 * planes. HSW primary planes no longer have this problem.
> -		 */
> -		if (IS_IVYBRIDGE(dev_priv)) {
> -			formats = ivb_primary_formats;
> -			num_formats = ARRAY_SIZE(ivb_primary_formats);
> -		} else {
> -			formats = i965_primary_formats;
> -			num_formats = ARRAY_SIZE(i965_primary_formats);
> -		}
> -	} else {
> -		formats = i8xx_primary_formats;
> -		num_formats = ARRAY_SIZE(i8xx_primary_formats);
> -	}
> -
> -	if (INTEL_GEN(dev_priv) >= 4)
> -		plane_funcs = &i965_plane_funcs;
> -	else
> -		plane_funcs = &i8xx_plane_funcs;
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		plane->min_cdclk = vlv_plane_min_cdclk;
> -	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> -		plane->min_cdclk = hsw_plane_min_cdclk;
> -	else if (IS_IVYBRIDGE(dev_priv))
> -		plane->min_cdclk = ivb_plane_min_cdclk;
> -	else
> -		plane->min_cdclk = i9xx_plane_min_cdclk;
> -
> -	plane->max_stride = i9xx_plane_max_stride;
> -	plane->update_plane = i9xx_update_plane;
> -	plane->disable_plane = i9xx_disable_plane;
> -	plane->get_hw_state = i9xx_plane_get_hw_state;
> -	plane->check_plane = i9xx_plane_check;
> -
> -	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> -		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> -					       0, plane_funcs,
> -					       formats, num_formats,
> -					       i9xx_format_modifiers,
> -					       DRM_PLANE_TYPE_PRIMARY,
> -					       "primary %c", pipe_name(pipe));
> -	else
> -		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> -					       0, plane_funcs,
> -					       formats, num_formats,
> -					       i9xx_format_modifiers,
> -					       DRM_PLANE_TYPE_PRIMARY,
> -					       "plane %c",
> -					       plane_name(plane->i9xx_plane));
> -	if (ret)
> -		goto fail;
> -
> -	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> -		supported_rotations =
> -			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
> -			DRM_MODE_REFLECT_X;
> -	} else if (INTEL_GEN(dev_priv) >= 4) {
> -		supported_rotations =
> -			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
> -	} else {
> -		supported_rotations = DRM_MODE_ROTATE_0;
> -	}
> -
> -	if (INTEL_GEN(dev_priv) >= 4)
> -		drm_plane_create_rotation_property(&plane->base,
> -						   DRM_MODE_ROTATE_0,
> -						   supported_rotations);
> -
> -	zpos = 0;
> -	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
> -
> -	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
> -
> -	return plane;
> -
> -fail:
> -	intel_plane_free(plane);
> -
> -	return ERR_PTR(ret);
> -}
> -
> -static int intel_crtc_late_register(struct drm_crtc *crtc)
> -{
> -	intel_crtc_debugfs_add(crtc);
> -	return 0;
> -}
> -
> -#define INTEL_CRTC_FUNCS \
> -	.gamma_set = drm_atomic_helper_legacy_gamma_set, \
> -	.set_config = drm_atomic_helper_set_config, \
> -	.destroy = intel_crtc_destroy, \
> -	.page_flip = drm_atomic_helper_page_flip, \
> -	.atomic_duplicate_state = intel_crtc_duplicate_state, \
> -	.atomic_destroy_state = intel_crtc_destroy_state, \
> -	.set_crc_source = intel_crtc_set_crc_source, \
> -	.verify_crc_source = intel_crtc_verify_crc_source, \
> -	.get_crc_sources = intel_crtc_get_crc_sources, \
> -	.late_register = intel_crtc_late_register
> -
> -static const struct drm_crtc_funcs bdw_crtc_funcs = {
> -	INTEL_CRTC_FUNCS,
> -
> -	.get_vblank_counter = g4x_get_vblank_counter,
> -	.enable_vblank = bdw_enable_vblank,
> -	.disable_vblank = bdw_disable_vblank,
> -	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs ilk_crtc_funcs = {
> -	INTEL_CRTC_FUNCS,
> -
> -	.get_vblank_counter = g4x_get_vblank_counter,
> -	.enable_vblank = ilk_enable_vblank,
> -	.disable_vblank = ilk_disable_vblank,
> -	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs g4x_crtc_funcs = {
> -	INTEL_CRTC_FUNCS,
> -
> -	.get_vblank_counter = g4x_get_vblank_counter,
> -	.enable_vblank = i965_enable_vblank,
> -	.disable_vblank = i965_disable_vblank,
> -	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i965_crtc_funcs = {
> -	INTEL_CRTC_FUNCS,
> -
> -	.get_vblank_counter = i915_get_vblank_counter,
> -	.enable_vblank = i965_enable_vblank,
> -	.disable_vblank = i965_disable_vblank,
> -	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i915gm_crtc_funcs = {
> -	INTEL_CRTC_FUNCS,
> -
> -	.get_vblank_counter = i915_get_vblank_counter,
> -	.enable_vblank = i915gm_enable_vblank,
> -	.disable_vblank = i915gm_disable_vblank,
> -	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i915_crtc_funcs = {
> -	INTEL_CRTC_FUNCS,
> -
> -	.get_vblank_counter = i915_get_vblank_counter,
> -	.enable_vblank = i8xx_enable_vblank,
> -	.disable_vblank = i8xx_disable_vblank,
> -	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i8xx_crtc_funcs = {
> -	INTEL_CRTC_FUNCS,
> -
> -	/* no hw vblank counter */
> -	.enable_vblank = i8xx_enable_vblank,
> -	.disable_vblank = i8xx_disable_vblank,
> -	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static struct intel_crtc *intel_crtc_alloc(void)
> -{
> -	struct intel_crtc_state *crtc_state;
> -	struct intel_crtc *crtc;
> -
> -	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
> -	if (!crtc)
> -		return ERR_PTR(-ENOMEM);
> -
> -	crtc_state = intel_crtc_state_alloc(crtc);
> -	if (!crtc_state) {
> -		kfree(crtc);
> -		return ERR_PTR(-ENOMEM);
> -	}
> -
> -	crtc->base.state = &crtc_state->uapi;
> -	crtc->config = crtc_state;
> -
> -	return crtc;
> -}
> -
> -static void intel_crtc_free(struct intel_crtc *crtc)
> -{
> -	intel_crtc_destroy_state(&crtc->base, crtc->base.state);
> -	kfree(crtc);
> -}
> -
>  static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_plane *plane;
> @@ -16591,100 +15753,6 @@ static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
>  	}
>  }
>  
> -static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
> -{
> -	struct intel_plane *primary, *cursor;
> -	const struct drm_crtc_funcs *funcs;
> -	struct intel_crtc *crtc;
> -	int sprite, ret;
> -
> -	crtc = intel_crtc_alloc();
> -	if (IS_ERR(crtc))
> -		return PTR_ERR(crtc);
> -
> -	crtc->pipe = pipe;
> -	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
> -
> -	primary = intel_primary_plane_create(dev_priv, pipe);
> -	if (IS_ERR(primary)) {
> -		ret = PTR_ERR(primary);
> -		goto fail;
> -	}
> -	crtc->plane_ids_mask |= BIT(primary->id);
> -
> -	for_each_sprite(dev_priv, pipe, sprite) {
> -		struct intel_plane *plane;
> -
> -		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
> -		if (IS_ERR(plane)) {
> -			ret = PTR_ERR(plane);
> -			goto fail;
> -		}
> -		crtc->plane_ids_mask |= BIT(plane->id);
> -	}
> -
> -	cursor = intel_cursor_plane_create(dev_priv, pipe);
> -	if (IS_ERR(cursor)) {
> -		ret = PTR_ERR(cursor);
> -		goto fail;
> -	}
> -	crtc->plane_ids_mask |= BIT(cursor->id);
> -
> -	if (HAS_GMCH(dev_priv)) {
> -		if (IS_CHERRYVIEW(dev_priv) ||
> -		    IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
> -			funcs = &g4x_crtc_funcs;
> -		else if (IS_GEN(dev_priv, 4))
> -			funcs = &i965_crtc_funcs;
> -		else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
> -			funcs = &i915gm_crtc_funcs;
> -		else if (IS_GEN(dev_priv, 3))
> -			funcs = &i915_crtc_funcs;
> -		else
> -			funcs = &i8xx_crtc_funcs;
> -	} else {
> -		if (INTEL_GEN(dev_priv) >= 8)
> -			funcs = &bdw_crtc_funcs;
> -		else
> -			funcs = &ilk_crtc_funcs;
> -	}
> -
> -	ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
> -					&primary->base, &cursor->base,
> -					funcs, "pipe %c", pipe_name(pipe));
> -	if (ret)
> -		goto fail;
> -
> -	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
> -	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
> -	dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
> -
> -	if (INTEL_GEN(dev_priv) < 9) {
> -		enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
> -
> -		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
> -		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
> -		dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
> -	}
> -
> -	if (INTEL_GEN(dev_priv) >= 10)
> -		drm_crtc_create_scaling_filter_property(&crtc->base,
> -						BIT(DRM_SCALING_FILTER_DEFAULT) |
> -						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
> -
> -	intel_color_init(crtc);
> -
> -	intel_crtc_crc_init(crtc);
> -
> -	drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
> -
> -	return 0;
> -
> -fail:
> -	intel_crtc_free(crtc);
> -
> -	return ret;
> -}
>  
>  int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
>  				      struct drm_file *file)
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index f0a5bf69656f..0eba91d18e96 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -659,6 +659,13 @@ struct intel_plane *
>  intel_cursor_plane_create(struct drm_i915_private *dev_priv,
>  			  enum pipe pipe);
>  
> +/* crtc */
> +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
> +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
> +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
> +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> +			    struct intel_crtc *crtc);
> +
>  /* modesetting */
>  void intel_modeset_init_hw(struct drm_i915_private *i915);
>  int intel_modeset_init_noirq(struct drm_i915_private *i915);
> -- 
> 2.27.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 6/9] drm/i915: refactor pll code out into intel_dpll_legacy.c
  2020-12-10  4:17 ` [Intel-gfx] [PATCH 6/9] drm/i915: refactor pll code out into intel_dpll_legacy.c Dave Airlie
@ 2020-12-10 15:18   ` Ville Syrjälä
  2020-12-10 16:31     ` Daniel Vetter
  0 siblings, 1 reply; 25+ messages in thread
From: Ville Syrjälä @ 2020-12-10 15:18 UTC (permalink / raw)
  To: Dave Airlie; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 02:17:52PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> This pulls a large chunk of the pll calculation code out of
> intel_display.c to a new file.
> 
> One function makse sense to be an inline, otherwise this
> is pretty much a straight copy cover. also all the
> remaining hooks for g45 and older end up the same now.
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |    1 +
>  drivers/gpu/drm/i915/display/intel_display.c  | 1393 +----------------
>  drivers/gpu/drm/i915/display/intel_display.h  |   13 +-
>  .../drm/i915/display/intel_display_types.h    |    5 +
>  .../gpu/drm/i915/display/intel_dpll_legacy.c  | 1370 ++++++++++++++++
>  5 files changed, 1398 insertions(+), 1384 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_dpll_legacy.c
> 
<snip>
> +static int hsw_crtc_compute_clock(struct intel_crtc *crtc,
> +				  struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	struct intel_atomic_state *state =
> +		to_intel_atomic_state(crtc_state->uapi.state);
> +
> +	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
> +	    INTEL_GEN(dev_priv) >= 11) {
> +		struct intel_encoder *encoder =
> +			intel_get_crtc_new_encoder(state, crtc_state);
> +
> +		if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
> +			drm_dbg_kms(&dev_priv->drm,
> +				    "failed to find PLL for pipe %c\n",
> +				    pipe_name(crtc->pipe));
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}

If you're moving this then the "legacy" in the fine name is just
wrong. I guess just call it intel_dpll.c if we lack a better idea?

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c
  2020-12-10 15:06   ` Ville Syrjälä
@ 2020-12-10 16:12     ` Jani Nikula
  2020-12-10 16:17       ` Daniel Vetter
  0 siblings, 1 reply; 25+ messages in thread
From: Jani Nikula @ 2020-12-10 16:12 UTC (permalink / raw)
  To: Ville Syrjälä, Dave Airlie; +Cc: intel-gfx

On Thu, 10 Dec 2020, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> On Thu, Dec 10, 2020 at 02:17:50PM +1000, Dave Airlie wrote:
>> From: Dave Airlie <airlied@redhat.com>
>> 
>> This file is a monster, let's start simple, the cursor plane code
>> seems pretty standalone, and splits out easily enough.
>> 
>> Signed-off-by: Dave Airlie <airlied@redhat.com>
>> ---
>>  drivers/gpu/drm/i915/Makefile                |   1 +
>>  drivers/gpu/drm/i915/display/intel_cursor.c  | 805 +++++++++++++++++++
>>  drivers/gpu/drm/i915/display/intel_display.c | 796 +-----------------
>>  drivers/gpu/drm/i915/display/intel_display.h |  12 +
>
> I would just add the intel_cursor.h for this. intel_display.h is an
> even bigger mess than intel_display.c, and causing no end of redundant
> rebuilds. The smaller we can make it the better IMO.

Separate header for each .c is where we've been heading since we started
refactoring the driver to multiple subdirs instead of the flat
structure, and started chopping up files as a consequence.

Also, please prefix the functions in intel_foo.[ch] with
intel_foo_. This is also where we've been heading for a while now.

BR,
Jani.



>
> Looks like a mechanical move, and seems to match my attempt at it so
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
>>  4 files changed, 824 insertions(+), 790 deletions(-)
>>  create mode 100644 drivers/gpu/drm/i915/display/intel_cursor.c
>> 
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index e5574e506a5c..98a35b939052 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -197,6 +197,7 @@ i915-y += \
>>  	display/intel_combo_phy.o \
>>  	display/intel_connector.o \
>>  	display/intel_csr.o \
>> +	display/intel_cursor.o \
>>  	display/intel_display.o \
>>  	display/intel_display_power.o \
>>  	display/intel_dpio_phy.o \
>> diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
>> new file mode 100644
>> index 000000000000..87a7a74a25ac
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/display/intel_cursor.c
>> @@ -0,0 +1,805 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2020 Intel Corporation
>> + */
>> +#include <linux/kernel.h>
>> +
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_atomic_uapi.h>
>> +#include <drm/drm_damage_helper.h>
>> +#include <drm/drm_plane_helper.h>
>> +#include <drm/drm_fourcc.h>
>> +
>> +#include "intel_atomic.h"
>> +#include "intel_atomic_plane.h"
>> +#include "intel_display_types.h"
>> +#include "intel_display.h"
>> +
>> +#include "intel_frontbuffer.h"
>> +#include "intel_pm.h"
>> +#include "intel_psr.h"
>> +#include "intel_sprite.h"
>> +
>> +/* Cursor formats */
>> +static const u32 intel_cursor_formats[] = {
>> +	DRM_FORMAT_ARGB8888,
>> +};
>> +
>> +static const u64 cursor_format_modifiers[] = {
>> +	DRM_FORMAT_MOD_LINEAR,
>> +	DRM_FORMAT_MOD_INVALID
>> +};
>> +
>> +static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
>> +{
>> +	struct drm_i915_private *dev_priv =
>> +		to_i915(plane_state->uapi.plane->dev);
>> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> +	const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>> +	u32 base;
>> +
>> +	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
>> +		base = sg_dma_address(obj->mm.pages->sgl);
>> +	else
>> +		base = intel_plane_ggtt_offset(plane_state);
>> +
>> +	return base + plane_state->color_plane[0].offset;
>> +}
>> +
>> +static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
>> +{
>> +	int x = plane_state->uapi.dst.x1;
>> +	int y = plane_state->uapi.dst.y1;
>> +	u32 pos = 0;
>> +
>> +	if (x < 0) {
>> +		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
>> +		x = -x;
>> +	}
>> +	pos |= x << CURSOR_X_SHIFT;
>> +
>> +	if (y < 0) {
>> +		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
>> +		y = -y;
>> +	}
>> +	pos |= y << CURSOR_Y_SHIFT;
>> +
>> +	return pos;
>> +}
>> +
>> +static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
>> +{
>> +	const struct drm_mode_config *config =
>> +		&plane_state->uapi.plane->dev->mode_config;
>> +	int width = drm_rect_width(&plane_state->uapi.dst);
>> +	int height = drm_rect_height(&plane_state->uapi.dst);
>> +
>> +	return width > 0 && width <= config->cursor_width &&
>> +		height > 0 && height <= config->cursor_height;
>> +}
>> +
>> +static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
>> +{
>> +	struct drm_i915_private *dev_priv =
>> +		to_i915(plane_state->uapi.plane->dev);
>> +	unsigned int rotation = plane_state->hw.rotation;
>> +	int src_x, src_y;
>> +	u32 offset;
>> +	int ret;
>> +
>> +	ret = intel_plane_compute_gtt(plane_state);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (!plane_state->uapi.visible)
>> +		return 0;
>> +
>> +	src_x = plane_state->uapi.src.x1 >> 16;
>> +	src_y = plane_state->uapi.src.y1 >> 16;
>> +
>> +	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
>> +	offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
>> +						    plane_state, 0);
>> +
>> +	if (src_x != 0 || src_y != 0) {
>> +		drm_dbg_kms(&dev_priv->drm,
>> +			    "Arbitrary cursor panning not supported\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/*
>> +	 * Put the final coordinates back so that the src
>> +	 * coordinate checks will see the right values.
>> +	 */
>> +	drm_rect_translate_to(&plane_state->uapi.src,
>> +			      src_x << 16, src_y << 16);
>> +
>> +	/* ILK+ do this automagically in hardware */
>> +	if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
>> +		const struct drm_framebuffer *fb = plane_state->hw.fb;
>> +		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
>> +		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
>> +
>> +		offset += (src_h * src_w - 1) * fb->format->cpp[0];
>> +	}
>> +
>> +	plane_state->color_plane[0].offset = offset;
>> +	plane_state->color_plane[0].x = src_x;
>> +	plane_state->color_plane[0].y = src_y;
>> +
>> +	return 0;
>> +}
>> +
>> +static int intel_check_cursor(struct intel_crtc_state *crtc_state,
>> +			      struct intel_plane_state *plane_state)
>> +{
>> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> +	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
>> +	const struct drm_rect src = plane_state->uapi.src;
>> +	const struct drm_rect dst = plane_state->uapi.dst;
>> +	int ret;
>> +
>> +	if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
>> +		drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
>> +						DRM_PLANE_HELPER_NO_SCALING,
>> +						DRM_PLANE_HELPER_NO_SCALING,
>> +						true);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* Use the unclipped src/dst rectangles, which we program to hw */
>> +	plane_state->uapi.src = src;
>> +	plane_state->uapi.dst = dst;
>> +
>> +	ret = intel_cursor_check_surface(plane_state);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (!plane_state->uapi.visible)
>> +		return 0;
>> +
>> +	ret = intel_plane_check_src_coordinates(plane_state);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static unsigned int
>> +i845_cursor_max_stride(struct intel_plane *plane,
>> +		       u32 pixel_format, u64 modifier,
>> +		       unsigned int rotation)
>> +{
>> +	return 2048;
>> +}
>> +
>> +static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
>> +{
>> +	u32 cntl = 0;
>> +
>> +	if (crtc_state->gamma_enable)
>> +		cntl |= CURSOR_GAMMA_ENABLE;
>> +
>> +	return cntl;
>> +}
>> +
>> +static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
>> +			   const struct intel_plane_state *plane_state)
>> +{
>> +	return CURSOR_ENABLE |
>> +		CURSOR_FORMAT_ARGB |
>> +		CURSOR_STRIDE(plane_state->color_plane[0].stride);
>> +}
>> +
>> +static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
>> +{
>> +	int width = drm_rect_width(&plane_state->uapi.dst);
>> +
>> +	/*
>> +	 * 845g/865g are only limited by the width of their cursors,
>> +	 * the height is arbitrary up to the precision of the register.
>> +	 */
>> +	return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
>> +}
>> +
>> +static int i845_check_cursor(struct intel_crtc_state *crtc_state,
>> +			     struct intel_plane_state *plane_state)
>> +{
>> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> +	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
>> +	int ret;
>> +
>> +	ret = intel_check_cursor(crtc_state, plane_state);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* if we want to turn off the cursor ignore width and height */
>> +	if (!fb)
>> +		return 0;
>> +
>> +	/* Check for which cursor types we support */
>> +	if (!i845_cursor_size_ok(plane_state)) {
>> +		drm_dbg_kms(&i915->drm,
>> +			    "Cursor dimension %dx%d not supported\n",
>> +			    drm_rect_width(&plane_state->uapi.dst),
>> +			    drm_rect_height(&plane_state->uapi.dst));
>> +		return -EINVAL;
>> +	}
>> +
>> +	drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
>> +		    plane_state->color_plane[0].stride != fb->pitches[0]);
>> +
>> +	switch (fb->pitches[0]) {
>> +	case 256:
>> +	case 512:
>> +	case 1024:
>> +	case 2048:
>> +		break;
>> +	default:
>> +		 drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
>> +			     fb->pitches[0]);
>> +		return -EINVAL;
>> +	}
>> +
>> +	plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
>> +
>> +	return 0;
>> +}
>> +
>> +static void i845_update_cursor(struct intel_plane *plane,
>> +			       const struct intel_crtc_state *crtc_state,
>> +			       const struct intel_plane_state *plane_state)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> +	u32 cntl = 0, base = 0, pos = 0, size = 0;
>> +	unsigned long irqflags;
>> +
>> +	if (plane_state && plane_state->uapi.visible) {
>> +		unsigned int width = drm_rect_width(&plane_state->uapi.dst);
>> +		unsigned int height = drm_rect_height(&plane_state->uapi.dst);
>> +
>> +		cntl = plane_state->ctl |
>> +			i845_cursor_ctl_crtc(crtc_state);
>> +
>> +		size = (height << 12) | width;
>> +
>> +		base = intel_cursor_base(plane_state);
>> +		pos = intel_cursor_position(plane_state);
>> +	}
>> +
>> +	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
>> +
>> +	/* On these chipsets we can only modify the base/size/stride
>> +	 * whilst the cursor is disabled.
>> +	 */
>> +	if (plane->cursor.base != base ||
>> +	    plane->cursor.size != size ||
>> +	    plane->cursor.cntl != cntl) {
>> +		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
>> +		intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
>> +		intel_de_write_fw(dev_priv, CURSIZE, size);
>> +		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
>> +		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
>> +
>> +		plane->cursor.base = base;
>> +		plane->cursor.size = size;
>> +		plane->cursor.cntl = cntl;
>> +	} else {
>> +		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
>> +	}
>> +
>> +	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>> +}
>> +
>> +static void i845_disable_cursor(struct intel_plane *plane,
>> +				const struct intel_crtc_state *crtc_state)
>> +{
>> +	i845_update_cursor(plane, crtc_state, NULL);
>> +}
>> +
>> +static bool i845_cursor_get_hw_state(struct intel_plane *plane,
>> +				     enum pipe *pipe)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> +	enum intel_display_power_domain power_domain;
>> +	intel_wakeref_t wakeref;
>> +	bool ret;
>> +
>> +	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
>> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
>> +	if (!wakeref)
>> +		return false;
>> +
>> +	ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
>> +
>> +	*pipe = PIPE_A;
>> +
>> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>> +
>> +	return ret;
>> +}
>> +
>> +static unsigned int
>> +i9xx_cursor_max_stride(struct intel_plane *plane,
>> +		       u32 pixel_format, u64 modifier,
>> +		       unsigned int rotation)
>> +{
>> +	return plane->base.dev->mode_config.cursor_width * 4;
>> +}
>> +
>> +static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
>> +{
>> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>> +	u32 cntl = 0;
>> +
>> +	if (INTEL_GEN(dev_priv) >= 11)
>> +		return cntl;
>> +
>> +	if (crtc_state->gamma_enable)
>> +		cntl = MCURSOR_GAMMA_ENABLE;
>> +
>> +	if (crtc_state->csc_enable)
>> +		cntl |= MCURSOR_PIPE_CSC_ENABLE;
>> +
>> +	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
>> +		cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
>> +
>> +	return cntl;
>> +}
>> +
>> +static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
>> +			   const struct intel_plane_state *plane_state)
>> +{
>> +	struct drm_i915_private *dev_priv =
>> +		to_i915(plane_state->uapi.plane->dev);
>> +	u32 cntl = 0;
>> +
>> +	if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
>> +		cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
>> +
>> +	switch (drm_rect_width(&plane_state->uapi.dst)) {
>> +	case 64:
>> +		cntl |= MCURSOR_MODE_64_ARGB_AX;
>> +		break;
>> +	case 128:
>> +		cntl |= MCURSOR_MODE_128_ARGB_AX;
>> +		break;
>> +	case 256:
>> +		cntl |= MCURSOR_MODE_256_ARGB_AX;
>> +		break;
>> +	default:
>> +		MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
>> +		return 0;
>> +	}
>> +
>> +	if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
>> +		cntl |= MCURSOR_ROTATE_180;
>> +
>> +	return cntl;
>> +}
>> +
>> +static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
>> +{
>> +	struct drm_i915_private *dev_priv =
>> +		to_i915(plane_state->uapi.plane->dev);
>> +	int width = drm_rect_width(&plane_state->uapi.dst);
>> +	int height = drm_rect_height(&plane_state->uapi.dst);
>> +
>> +	if (!intel_cursor_size_ok(plane_state))
>> +		return false;
>> +
>> +	/* Cursor width is limited to a few power-of-two sizes */
>> +	switch (width) {
>> +	case 256:
>> +	case 128:
>> +	case 64:
>> +		break;
>> +	default:
>> +		return false;
>> +	}
>> +
>> +	/*
>> +	 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
>> +	 * height from 8 lines up to the cursor width, when the
>> +	 * cursor is not rotated. Everything else requires square
>> +	 * cursors.
>> +	 */
>> +	if (HAS_CUR_FBC(dev_priv) &&
>> +	    plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
>> +		if (height < 8 || height > width)
>> +			return false;
>> +	} else {
>> +		if (height != width)
>> +			return false;
>> +	}
>> +
>> +	return true;
>> +}
>> +
>> +static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
>> +			     struct intel_plane_state *plane_state)
>> +{
>> +	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
>> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> +	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> +	enum pipe pipe = plane->pipe;
>> +	int ret;
>> +
>> +	ret = intel_check_cursor(crtc_state, plane_state);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* if we want to turn off the cursor ignore width and height */
>> +	if (!fb)
>> +		return 0;
>> +
>> +	/* Check for which cursor types we support */
>> +	if (!i9xx_cursor_size_ok(plane_state)) {
>> +		drm_dbg(&dev_priv->drm,
>> +			"Cursor dimension %dx%d not supported\n",
>> +			drm_rect_width(&plane_state->uapi.dst),
>> +			drm_rect_height(&plane_state->uapi.dst));
>> +		return -EINVAL;
>> +	}
>> +
>> +	drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
>> +		    plane_state->color_plane[0].stride != fb->pitches[0]);
>> +
>> +	if (fb->pitches[0] !=
>> +	    drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
>> +		drm_dbg_kms(&dev_priv->drm,
>> +			    "Invalid cursor stride (%u) (cursor width %d)\n",
>> +			    fb->pitches[0],
>> +			    drm_rect_width(&plane_state->uapi.dst));
>> +		return -EINVAL;
>> +	}
>> +
>> +	/*
>> +	 * There's something wrong with the cursor on CHV pipe C.
>> +	 * If it straddles the left edge of the screen then
>> +	 * moving it away from the edge or disabling it often
>> +	 * results in a pipe underrun, and often that can lead to
>> +	 * dead pipe (constant underrun reported, and it scans
>> +	 * out just a solid color). To recover from that, the
>> +	 * display power well must be turned off and on again.
>> +	 * Refuse the put the cursor into that compromised position.
>> +	 */
>> +	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
>> +	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
>> +		drm_dbg_kms(&dev_priv->drm,
>> +			    "CHV cursor C not allowed to straddle the left screen edge\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
>> +
>> +	return 0;
>> +}
>> +
>> +static void i9xx_update_cursor(struct intel_plane *plane,
>> +			       const struct intel_crtc_state *crtc_state,
>> +			       const struct intel_plane_state *plane_state)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> +	enum pipe pipe = plane->pipe;
>> +	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
>> +	unsigned long irqflags;
>> +
>> +	if (plane_state && plane_state->uapi.visible) {
>> +		unsigned width = drm_rect_width(&plane_state->uapi.dst);
>> +		unsigned height = drm_rect_height(&plane_state->uapi.dst);
>> +
>> +		cntl = plane_state->ctl |
>> +			i9xx_cursor_ctl_crtc(crtc_state);
>> +
>> +		if (width != height)
>> +			fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
>> +
>> +		base = intel_cursor_base(plane_state);
>> +		pos = intel_cursor_position(plane_state);
>> +	}
>> +
>> +	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
>> +
>> +	/*
>> +	 * On some platforms writing CURCNTR first will also
>> +	 * cause CURPOS to be armed by the CURBASE write.
>> +	 * Without the CURCNTR write the CURPOS write would
>> +	 * arm itself. Thus we always update CURCNTR before
>> +	 * CURPOS.
>> +	 *
>> +	 * On other platforms CURPOS always requires the
>> +	 * CURBASE write to arm the update. Additonally
>> +	 * a write to any of the cursor register will cancel
>> +	 * an already armed cursor update. Thus leaving out
>> +	 * the CURBASE write after CURPOS could lead to a
>> +	 * cursor that doesn't appear to move, or even change
>> +	 * shape. Thus we always write CURBASE.
>> +	 *
>> +	 * The other registers are armed by by the CURBASE write
>> +	 * except when the plane is getting enabled at which time
>> +	 * the CURCNTR write arms the update.
>> +	 */
>> +
>> +	if (INTEL_GEN(dev_priv) >= 9)
>> +		skl_write_cursor_wm(plane, crtc_state);
>> +
>> +	if (!intel_crtc_needs_modeset(crtc_state))
>> +		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
>> +
>> +	if (plane->cursor.base != base ||
>> +	    plane->cursor.size != fbc_ctl ||
>> +	    plane->cursor.cntl != cntl) {
>> +		if (HAS_CUR_FBC(dev_priv))
>> +			intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
>> +					  fbc_ctl);
>> +		intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
>> +		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
>> +		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
>> +
>> +		plane->cursor.base = base;
>> +		plane->cursor.size = fbc_ctl;
>> +		plane->cursor.cntl = cntl;
>> +	} else {
>> +		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
>> +		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
>> +	}
>> +
>> +	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>> +}
>> +
>> +static void i9xx_disable_cursor(struct intel_plane *plane,
>> +				const struct intel_crtc_state *crtc_state)
>> +{
>> +	i9xx_update_cursor(plane, crtc_state, NULL);
>> +}
>> +
>> +static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
>> +				     enum pipe *pipe)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> +	enum intel_display_power_domain power_domain;
>> +	intel_wakeref_t wakeref;
>> +	bool ret;
>> +	u32 val;
>> +
>> +	/*
>> +	 * Not 100% correct for planes that can move between pipes,
>> +	 * but that's only the case for gen2-3 which don't have any
>> +	 * display power wells.
>> +	 */
>> +	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
>> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
>> +	if (!wakeref)
>> +		return false;
>> +
>> +	val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
>> +
>> +	ret = val & MCURSOR_MODE;
>> +
>> +	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>> +		*pipe = plane->pipe;
>> +	else
>> +		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
>> +			MCURSOR_PIPE_SELECT_SHIFT;
>> +
>> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>> +
>> +	return ret;
>> +}
>> +
>> +static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
>> +					      u32 format, u64 modifier)
>> +{
>> +	return modifier == DRM_FORMAT_MOD_LINEAR &&
>> +		format == DRM_FORMAT_ARGB8888;
>> +}
>> +
>> +static int
>> +intel_legacy_cursor_update(struct drm_plane *_plane,
>> +			   struct drm_crtc *_crtc,
>> +			   struct drm_framebuffer *fb,
>> +			   int crtc_x, int crtc_y,
>> +			   unsigned int crtc_w, unsigned int crtc_h,
>> +			   u32 src_x, u32 src_y,
>> +			   u32 src_w, u32 src_h,
>> +			   struct drm_modeset_acquire_ctx *ctx)
>> +{
>> +	struct intel_plane *plane = to_intel_plane(_plane);
>> +	struct intel_crtc *crtc = to_intel_crtc(_crtc);
>> +	struct intel_plane_state *old_plane_state =
>> +		to_intel_plane_state(plane->base.state);
>> +	struct intel_plane_state *new_plane_state;
>> +	struct intel_crtc_state *crtc_state =
>> +		to_intel_crtc_state(crtc->base.state);
>> +	struct intel_crtc_state *new_crtc_state;
>> +	int ret;
>> +
>> +	/*
>> +	 * When crtc is inactive or there is a modeset pending,
>> +	 * wait for it to complete in the slowpath
>> +	 *
>> +	 * FIXME bigjoiner fastpath would be good
>> +	 */
>> +	if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
>> +	    crtc_state->update_pipe || crtc_state->bigjoiner)
>> +		goto slow;
>> +
>> +	/*
>> +	 * Don't do an async update if there is an outstanding commit modifying
>> +	 * the plane.  This prevents our async update's changes from getting
>> +	 * overridden by a previous synchronous update's state.
>> +	 */
>> +	if (old_plane_state->uapi.commit &&
>> +	    !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
>> +		goto slow;
>> +
>> +	/*
>> +	 * If any parameters change that may affect watermarks,
>> +	 * take the slowpath. Only changing fb or position should be
>> +	 * in the fastpath.
>> +	 */
>> +	if (old_plane_state->uapi.crtc != &crtc->base ||
>> +	    old_plane_state->uapi.src_w != src_w ||
>> +	    old_plane_state->uapi.src_h != src_h ||
>> +	    old_plane_state->uapi.crtc_w != crtc_w ||
>> +	    old_plane_state->uapi.crtc_h != crtc_h ||
>> +	    !old_plane_state->uapi.fb != !fb)
>> +		goto slow;
>> +
>> +	new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
>> +	if (!new_plane_state)
>> +		return -ENOMEM;
>> +
>> +	new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
>> +	if (!new_crtc_state) {
>> +		ret = -ENOMEM;
>> +		goto out_free;
>> +	}
>> +
>> +	drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
>> +
>> +	new_plane_state->uapi.src_x = src_x;
>> +	new_plane_state->uapi.src_y = src_y;
>> +	new_plane_state->uapi.src_w = src_w;
>> +	new_plane_state->uapi.src_h = src_h;
>> +	new_plane_state->uapi.crtc_x = crtc_x;
>> +	new_plane_state->uapi.crtc_y = crtc_y;
>> +	new_plane_state->uapi.crtc_w = crtc_w;
>> +	new_plane_state->uapi.crtc_h = crtc_h;
>> +
>> +	intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
>> +
>> +	ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
>> +						  old_plane_state, new_plane_state);
>> +	if (ret)
>> +		goto out_free;
>> +
>> +	ret = intel_plane_pin_fb(new_plane_state);
>> +	if (ret)
>> +		goto out_free;
>> +
>> +	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
>> +				ORIGIN_FLIP);
>> +	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
>> +				to_intel_frontbuffer(new_plane_state->hw.fb),
>> +				plane->frontbuffer_bit);
>> +
>> +	/* Swap plane state */
>> +	plane->base.state = &new_plane_state->uapi;
>> +
>> +	/*
>> +	 * We cannot swap crtc_state as it may be in use by an atomic commit or
>> +	 * page flip that's running simultaneously. If we swap crtc_state and
>> +	 * destroy the old state, we will cause a use-after-free there.
>> +	 *
>> +	 * Only update active_planes, which is needed for our internal
>> +	 * bookkeeping. Either value will do the right thing when updating
>> +	 * planes atomically. If the cursor was part of the atomic update then
>> +	 * we would have taken the slowpath.
>> +	 */
>> +	crtc_state->active_planes = new_crtc_state->active_planes;
>> +
>> +	if (new_plane_state->uapi.visible)
>> +		intel_update_plane(plane, crtc_state, new_plane_state);
>> +	else
>> +		intel_disable_plane(plane, crtc_state);
>> +
>> +	intel_plane_unpin_fb(old_plane_state);
>> +
>> +out_free:
>> +	if (new_crtc_state)
>> +		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
>> +	if (ret)
>> +		intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
>> +	else
>> +		intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
>> +	return ret;
>> +
>> +slow:
>> +	return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
>> +					      crtc_x, crtc_y, crtc_w, crtc_h,
>> +					      src_x, src_y, src_w, src_h, ctx);
>> +}
>> +
>> +static const struct drm_plane_funcs intel_cursor_plane_funcs = {
>> +	.update_plane = intel_legacy_cursor_update,
>> +	.disable_plane = drm_atomic_helper_disable_plane,
>> +	.destroy = intel_plane_destroy,
>> +	.atomic_duplicate_state = intel_plane_duplicate_state,
>> +	.atomic_destroy_state = intel_plane_destroy_state,
>> +	.format_mod_supported = intel_cursor_format_mod_supported,
>> +};
>> +
>> +struct intel_plane *
>> +intel_cursor_plane_create(struct drm_i915_private *dev_priv,
>> +			  enum pipe pipe)
>> +{
>> +	struct intel_plane *cursor;
>> +	int ret, zpos;
>> +
>> +	cursor = intel_plane_alloc();
>> +	if (IS_ERR(cursor))
>> +		return cursor;
>> +
>> +	cursor->pipe = pipe;
>> +	cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
>> +	cursor->id = PLANE_CURSOR;
>> +	cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
>> +
>> +	if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
>> +		cursor->max_stride = i845_cursor_max_stride;
>> +		cursor->update_plane = i845_update_cursor;
>> +		cursor->disable_plane = i845_disable_cursor;
>> +		cursor->get_hw_state = i845_cursor_get_hw_state;
>> +		cursor->check_plane = i845_check_cursor;
>> +	} else {
>> +		cursor->max_stride = i9xx_cursor_max_stride;
>> +		cursor->update_plane = i9xx_update_cursor;
>> +		cursor->disable_plane = i9xx_disable_cursor;
>> +		cursor->get_hw_state = i9xx_cursor_get_hw_state;
>> +		cursor->check_plane = i9xx_check_cursor;
>> +	}
>> +
>> +	cursor->cursor.base = ~0;
>> +	cursor->cursor.cntl = ~0;
>> +
>> +	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
>> +		cursor->cursor.size = ~0;
>> +
>> +	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
>> +				       0, &intel_cursor_plane_funcs,
>> +				       intel_cursor_formats,
>> +				       ARRAY_SIZE(intel_cursor_formats),
>> +				       cursor_format_modifiers,
>> +				       DRM_PLANE_TYPE_CURSOR,
>> +				       "cursor %c", pipe_name(pipe));
>> +	if (ret)
>> +		goto fail;
>> +
>> +	if (INTEL_GEN(dev_priv) >= 4)
>> +		drm_plane_create_rotation_property(&cursor->base,
>> +						   DRM_MODE_ROTATE_0,
>> +						   DRM_MODE_ROTATE_0 |
>> +						   DRM_MODE_ROTATE_180);
>> +
>> +	zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
>> +	drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
>> +
>> +	if (INTEL_GEN(dev_priv) >= 12)
>> +		drm_plane_enable_fb_damage_clips(&cursor->base);
>> +
>> +	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
>> +
>> +	return cursor;
>> +
>> +fail:
>> +	intel_plane_free(cursor);
>> +
>> +	return ERR_PTR(ret);
>> +}
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>> index 79d7479beed2..722a1cf61941 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -137,16 +137,6 @@ static const u64 i9xx_format_modifiers[] = {
>>  	DRM_FORMAT_MOD_INVALID
>>  };
>>  
>> -/* Cursor formats */
>> -static const u32 intel_cursor_formats[] = {
>> -	DRM_FORMAT_ARGB8888,
>> -};
>> -
>> -static const u64 cursor_format_modifiers[] = {
>> -	DRM_FORMAT_MOD_LINEAR,
>> -	DRM_FORMAT_MOD_INVALID
>> -};
>> -
>>  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
>>  				struct intel_crtc_state *pipe_config);
>>  static void ilk_pch_clock_get(struct intel_crtc *crtc,
>> @@ -2528,9 +2518,9 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,
>>  	return offset_aligned;
>>  }
>>  
>> -static u32 intel_plane_compute_aligned_offset(int *x, int *y,
>> -					      const struct intel_plane_state *state,
>> -					      int color_plane)
>> +u32 intel_plane_compute_aligned_offset(int *x, int *y,
>> +				       const struct intel_plane_state *state,
>> +				       int color_plane)
>>  {
>>  	struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane);
>>  	struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
>> @@ -3267,7 +3257,7 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)
>>  	}
>>  }
>>  
>> -static int
>> +int
>>  intel_plane_compute_gtt(struct intel_plane_state *plane_state)
>>  {
>>  	const struct intel_framebuffer *fb =
>> @@ -11536,569 +11526,6 @@ static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state)
>>  	return true;
>>  }
>>  
>> -static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
>> -{
>> -	struct drm_i915_private *dev_priv =
>> -		to_i915(plane_state->uapi.plane->dev);
>> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> -	const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>> -	u32 base;
>> -
>> -	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
>> -		base = sg_dma_address(obj->mm.pages->sgl);
>> -	else
>> -		base = intel_plane_ggtt_offset(plane_state);
>> -
>> -	return base + plane_state->color_plane[0].offset;
>> -}
>> -
>> -static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
>> -{
>> -	int x = plane_state->uapi.dst.x1;
>> -	int y = plane_state->uapi.dst.y1;
>> -	u32 pos = 0;
>> -
>> -	if (x < 0) {
>> -		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
>> -		x = -x;
>> -	}
>> -	pos |= x << CURSOR_X_SHIFT;
>> -
>> -	if (y < 0) {
>> -		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
>> -		y = -y;
>> -	}
>> -	pos |= y << CURSOR_Y_SHIFT;
>> -
>> -	return pos;
>> -}
>> -
>> -static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
>> -{
>> -	const struct drm_mode_config *config =
>> -		&plane_state->uapi.plane->dev->mode_config;
>> -	int width = drm_rect_width(&plane_state->uapi.dst);
>> -	int height = drm_rect_height(&plane_state->uapi.dst);
>> -
>> -	return width > 0 && width <= config->cursor_width &&
>> -		height > 0 && height <= config->cursor_height;
>> -}
>> -
>> -static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
>> -{
>> -	struct drm_i915_private *dev_priv =
>> -		to_i915(plane_state->uapi.plane->dev);
>> -	unsigned int rotation = plane_state->hw.rotation;
>> -	int src_x, src_y;
>> -	u32 offset;
>> -	int ret;
>> -
>> -	ret = intel_plane_compute_gtt(plane_state);
>> -	if (ret)
>> -		return ret;
>> -
>> -	if (!plane_state->uapi.visible)
>> -		return 0;
>> -
>> -	src_x = plane_state->uapi.src.x1 >> 16;
>> -	src_y = plane_state->uapi.src.y1 >> 16;
>> -
>> -	intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
>> -	offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
>> -						    plane_state, 0);
>> -
>> -	if (src_x != 0 || src_y != 0) {
>> -		drm_dbg_kms(&dev_priv->drm,
>> -			    "Arbitrary cursor panning not supported\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	/*
>> -	 * Put the final coordinates back so that the src
>> -	 * coordinate checks will see the right values.
>> -	 */
>> -	drm_rect_translate_to(&plane_state->uapi.src,
>> -			      src_x << 16, src_y << 16);
>> -
>> -	/* ILK+ do this automagically in hardware */
>> -	if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
>> -		const struct drm_framebuffer *fb = plane_state->hw.fb;
>> -		int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
>> -		int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
>> -
>> -		offset += (src_h * src_w - 1) * fb->format->cpp[0];
>> -	}
>> -
>> -	plane_state->color_plane[0].offset = offset;
>> -	plane_state->color_plane[0].x = src_x;
>> -	plane_state->color_plane[0].y = src_y;
>> -
>> -	return 0;
>> -}
>> -
>> -static int intel_check_cursor(struct intel_crtc_state *crtc_state,
>> -			      struct intel_plane_state *plane_state)
>> -{
>> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> -	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
>> -	const struct drm_rect src = plane_state->uapi.src;
>> -	const struct drm_rect dst = plane_state->uapi.dst;
>> -	int ret;
>> -
>> -	if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
>> -		drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
>> -						DRM_PLANE_HELPER_NO_SCALING,
>> -						DRM_PLANE_HELPER_NO_SCALING,
>> -						true);
>> -	if (ret)
>> -		return ret;
>> -
>> -	/* Use the unclipped src/dst rectangles, which we program to hw */
>> -	plane_state->uapi.src = src;
>> -	plane_state->uapi.dst = dst;
>> -
>> -	ret = intel_cursor_check_surface(plane_state);
>> -	if (ret)
>> -		return ret;
>> -
>> -	if (!plane_state->uapi.visible)
>> -		return 0;
>> -
>> -	ret = intel_plane_check_src_coordinates(plane_state);
>> -	if (ret)
>> -		return ret;
>> -
>> -	return 0;
>> -}
>> -
>> -static unsigned int
>> -i845_cursor_max_stride(struct intel_plane *plane,
>> -		       u32 pixel_format, u64 modifier,
>> -		       unsigned int rotation)
>> -{
>> -	return 2048;
>> -}
>> -
>> -static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
>> -{
>> -	u32 cntl = 0;
>> -
>> -	if (crtc_state->gamma_enable)
>> -		cntl |= CURSOR_GAMMA_ENABLE;
>> -
>> -	return cntl;
>> -}
>> -
>> -static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
>> -			   const struct intel_plane_state *plane_state)
>> -{
>> -	return CURSOR_ENABLE |
>> -		CURSOR_FORMAT_ARGB |
>> -		CURSOR_STRIDE(plane_state->color_plane[0].stride);
>> -}
>> -
>> -static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
>> -{
>> -	int width = drm_rect_width(&plane_state->uapi.dst);
>> -
>> -	/*
>> -	 * 845g/865g are only limited by the width of their cursors,
>> -	 * the height is arbitrary up to the precision of the register.
>> -	 */
>> -	return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
>> -}
>> -
>> -static int i845_check_cursor(struct intel_crtc_state *crtc_state,
>> -			     struct intel_plane_state *plane_state)
>> -{
>> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> -	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
>> -	int ret;
>> -
>> -	ret = intel_check_cursor(crtc_state, plane_state);
>> -	if (ret)
>> -		return ret;
>> -
>> -	/* if we want to turn off the cursor ignore width and height */
>> -	if (!fb)
>> -		return 0;
>> -
>> -	/* Check for which cursor types we support */
>> -	if (!i845_cursor_size_ok(plane_state)) {
>> -		drm_dbg_kms(&i915->drm,
>> -			    "Cursor dimension %dx%d not supported\n",
>> -			    drm_rect_width(&plane_state->uapi.dst),
>> -			    drm_rect_height(&plane_state->uapi.dst));
>> -		return -EINVAL;
>> -	}
>> -
>> -	drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
>> -		    plane_state->color_plane[0].stride != fb->pitches[0]);
>> -
>> -	switch (fb->pitches[0]) {
>> -	case 256:
>> -	case 512:
>> -	case 1024:
>> -	case 2048:
>> -		break;
>> -	default:
>> -		 drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
>> -			     fb->pitches[0]);
>> -		return -EINVAL;
>> -	}
>> -
>> -	plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
>> -
>> -	return 0;
>> -}
>> -
>> -static void i845_update_cursor(struct intel_plane *plane,
>> -			       const struct intel_crtc_state *crtc_state,
>> -			       const struct intel_plane_state *plane_state)
>> -{
>> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> -	u32 cntl = 0, base = 0, pos = 0, size = 0;
>> -	unsigned long irqflags;
>> -
>> -	if (plane_state && plane_state->uapi.visible) {
>> -		unsigned int width = drm_rect_width(&plane_state->uapi.dst);
>> -		unsigned int height = drm_rect_height(&plane_state->uapi.dst);
>> -
>> -		cntl = plane_state->ctl |
>> -			i845_cursor_ctl_crtc(crtc_state);
>> -
>> -		size = (height << 12) | width;
>> -
>> -		base = intel_cursor_base(plane_state);
>> -		pos = intel_cursor_position(plane_state);
>> -	}
>> -
>> -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
>> -
>> -	/* On these chipsets we can only modify the base/size/stride
>> -	 * whilst the cursor is disabled.
>> -	 */
>> -	if (plane->cursor.base != base ||
>> -	    plane->cursor.size != size ||
>> -	    plane->cursor.cntl != cntl) {
>> -		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
>> -		intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
>> -		intel_de_write_fw(dev_priv, CURSIZE, size);
>> -		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
>> -		intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
>> -
>> -		plane->cursor.base = base;
>> -		plane->cursor.size = size;
>> -		plane->cursor.cntl = cntl;
>> -	} else {
>> -		intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
>> -	}
>> -
>> -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>> -}
>> -
>> -static void i845_disable_cursor(struct intel_plane *plane,
>> -				const struct intel_crtc_state *crtc_state)
>> -{
>> -	i845_update_cursor(plane, crtc_state, NULL);
>> -}
>> -
>> -static bool i845_cursor_get_hw_state(struct intel_plane *plane,
>> -				     enum pipe *pipe)
>> -{
>> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> -	enum intel_display_power_domain power_domain;
>> -	intel_wakeref_t wakeref;
>> -	bool ret;
>> -
>> -	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
>> -	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
>> -	if (!wakeref)
>> -		return false;
>> -
>> -	ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
>> -
>> -	*pipe = PIPE_A;
>> -
>> -	intel_display_power_put(dev_priv, power_domain, wakeref);
>> -
>> -	return ret;
>> -}
>> -
>> -static unsigned int
>> -i9xx_cursor_max_stride(struct intel_plane *plane,
>> -		       u32 pixel_format, u64 modifier,
>> -		       unsigned int rotation)
>> -{
>> -	return plane->base.dev->mode_config.cursor_width * 4;
>> -}
>> -
>> -static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
>> -{
>> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>> -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>> -	u32 cntl = 0;
>> -
>> -	if (INTEL_GEN(dev_priv) >= 11)
>> -		return cntl;
>> -
>> -	if (crtc_state->gamma_enable)
>> -		cntl = MCURSOR_GAMMA_ENABLE;
>> -
>> -	if (crtc_state->csc_enable)
>> -		cntl |= MCURSOR_PIPE_CSC_ENABLE;
>> -
>> -	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
>> -		cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
>> -
>> -	return cntl;
>> -}
>> -
>> -static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
>> -			   const struct intel_plane_state *plane_state)
>> -{
>> -	struct drm_i915_private *dev_priv =
>> -		to_i915(plane_state->uapi.plane->dev);
>> -	u32 cntl = 0;
>> -
>> -	if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
>> -		cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
>> -
>> -	switch (drm_rect_width(&plane_state->uapi.dst)) {
>> -	case 64:
>> -		cntl |= MCURSOR_MODE_64_ARGB_AX;
>> -		break;
>> -	case 128:
>> -		cntl |= MCURSOR_MODE_128_ARGB_AX;
>> -		break;
>> -	case 256:
>> -		cntl |= MCURSOR_MODE_256_ARGB_AX;
>> -		break;
>> -	default:
>> -		MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
>> -		return 0;
>> -	}
>> -
>> -	if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
>> -		cntl |= MCURSOR_ROTATE_180;
>> -
>> -	return cntl;
>> -}
>> -
>> -static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
>> -{
>> -	struct drm_i915_private *dev_priv =
>> -		to_i915(plane_state->uapi.plane->dev);
>> -	int width = drm_rect_width(&plane_state->uapi.dst);
>> -	int height = drm_rect_height(&plane_state->uapi.dst);
>> -
>> -	if (!intel_cursor_size_ok(plane_state))
>> -		return false;
>> -
>> -	/* Cursor width is limited to a few power-of-two sizes */
>> -	switch (width) {
>> -	case 256:
>> -	case 128:
>> -	case 64:
>> -		break;
>> -	default:
>> -		return false;
>> -	}
>> -
>> -	/*
>> -	 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
>> -	 * height from 8 lines up to the cursor width, when the
>> -	 * cursor is not rotated. Everything else requires square
>> -	 * cursors.
>> -	 */
>> -	if (HAS_CUR_FBC(dev_priv) &&
>> -	    plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
>> -		if (height < 8 || height > width)
>> -			return false;
>> -	} else {
>> -		if (height != width)
>> -			return false;
>> -	}
>> -
>> -	return true;
>> -}
>> -
>> -static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
>> -			     struct intel_plane_state *plane_state)
>> -{
>> -	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
>> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> -	const struct drm_framebuffer *fb = plane_state->hw.fb;
>> -	enum pipe pipe = plane->pipe;
>> -	int ret;
>> -
>> -	ret = intel_check_cursor(crtc_state, plane_state);
>> -	if (ret)
>> -		return ret;
>> -
>> -	/* if we want to turn off the cursor ignore width and height */
>> -	if (!fb)
>> -		return 0;
>> -
>> -	/* Check for which cursor types we support */
>> -	if (!i9xx_cursor_size_ok(plane_state)) {
>> -		drm_dbg(&dev_priv->drm,
>> -			"Cursor dimension %dx%d not supported\n",
>> -			drm_rect_width(&plane_state->uapi.dst),
>> -			drm_rect_height(&plane_state->uapi.dst));
>> -		return -EINVAL;
>> -	}
>> -
>> -	drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
>> -		    plane_state->color_plane[0].stride != fb->pitches[0]);
>> -
>> -	if (fb->pitches[0] !=
>> -	    drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
>> -		drm_dbg_kms(&dev_priv->drm,
>> -			    "Invalid cursor stride (%u) (cursor width %d)\n",
>> -			    fb->pitches[0],
>> -			    drm_rect_width(&plane_state->uapi.dst));
>> -		return -EINVAL;
>> -	}
>> -
>> -	/*
>> -	 * There's something wrong with the cursor on CHV pipe C.
>> -	 * If it straddles the left edge of the screen then
>> -	 * moving it away from the edge or disabling it often
>> -	 * results in a pipe underrun, and often that can lead to
>> -	 * dead pipe (constant underrun reported, and it scans
>> -	 * out just a solid color). To recover from that, the
>> -	 * display power well must be turned off and on again.
>> -	 * Refuse the put the cursor into that compromised position.
>> -	 */
>> -	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
>> -	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
>> -		drm_dbg_kms(&dev_priv->drm,
>> -			    "CHV cursor C not allowed to straddle the left screen edge\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
>> -
>> -	return 0;
>> -}
>> -
>> -static void i9xx_update_cursor(struct intel_plane *plane,
>> -			       const struct intel_crtc_state *crtc_state,
>> -			       const struct intel_plane_state *plane_state)
>> -{
>> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> -	enum pipe pipe = plane->pipe;
>> -	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
>> -	unsigned long irqflags;
>> -
>> -	if (plane_state && plane_state->uapi.visible) {
>> -		unsigned width = drm_rect_width(&plane_state->uapi.dst);
>> -		unsigned height = drm_rect_height(&plane_state->uapi.dst);
>> -
>> -		cntl = plane_state->ctl |
>> -			i9xx_cursor_ctl_crtc(crtc_state);
>> -
>> -		if (width != height)
>> -			fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
>> -
>> -		base = intel_cursor_base(plane_state);
>> -		pos = intel_cursor_position(plane_state);
>> -	}
>> -
>> -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
>> -
>> -	/*
>> -	 * On some platforms writing CURCNTR first will also
>> -	 * cause CURPOS to be armed by the CURBASE write.
>> -	 * Without the CURCNTR write the CURPOS write would
>> -	 * arm itself. Thus we always update CURCNTR before
>> -	 * CURPOS.
>> -	 *
>> -	 * On other platforms CURPOS always requires the
>> -	 * CURBASE write to arm the update. Additonally
>> -	 * a write to any of the cursor register will cancel
>> -	 * an already armed cursor update. Thus leaving out
>> -	 * the CURBASE write after CURPOS could lead to a
>> -	 * cursor that doesn't appear to move, or even change
>> -	 * shape. Thus we always write CURBASE.
>> -	 *
>> -	 * The other registers are armed by by the CURBASE write
>> -	 * except when the plane is getting enabled at which time
>> -	 * the CURCNTR write arms the update.
>> -	 */
>> -
>> -	if (INTEL_GEN(dev_priv) >= 9)
>> -		skl_write_cursor_wm(plane, crtc_state);
>> -
>> -	if (!intel_crtc_needs_modeset(crtc_state))
>> -		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
>> -
>> -	if (plane->cursor.base != base ||
>> -	    plane->cursor.size != fbc_ctl ||
>> -	    plane->cursor.cntl != cntl) {
>> -		if (HAS_CUR_FBC(dev_priv))
>> -			intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
>> -					  fbc_ctl);
>> -		intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
>> -		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
>> -		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
>> -
>> -		plane->cursor.base = base;
>> -		plane->cursor.size = fbc_ctl;
>> -		plane->cursor.cntl = cntl;
>> -	} else {
>> -		intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
>> -		intel_de_write_fw(dev_priv, CURBASE(pipe), base);
>> -	}
>> -
>> -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>> -}
>> -
>> -static void i9xx_disable_cursor(struct intel_plane *plane,
>> -				const struct intel_crtc_state *crtc_state)
>> -{
>> -	i9xx_update_cursor(plane, crtc_state, NULL);
>> -}
>> -
>> -static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
>> -				     enum pipe *pipe)
>> -{
>> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> -	enum intel_display_power_domain power_domain;
>> -	intel_wakeref_t wakeref;
>> -	bool ret;
>> -	u32 val;
>> -
>> -	/*
>> -	 * Not 100% correct for planes that can move between pipes,
>> -	 * but that's only the case for gen2-3 which don't have any
>> -	 * display power wells.
>> -	 */
>> -	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
>> -	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
>> -	if (!wakeref)
>> -		return false;
>> -
>> -	val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
>> -
>> -	ret = val & MCURSOR_MODE;
>> -
>> -	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>> -		*pipe = plane->pipe;
>> -	else
>> -		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
>> -			MCURSOR_PIPE_SELECT_SHIFT;
>> -
>> -	intel_display_power_put(dev_priv, power_domain, wakeref);
>> -
>> -	return ret;
>> -}
>> -
>>  /* VESA 640x480x72Hz mode to set on the pipe */
>>  static const struct drm_display_mode load_detect_mode = {
>>  	DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
>> @@ -16609,7 +16036,7 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc,
>>  	add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
>>  }
>>  
>> -static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
>> +int intel_plane_pin_fb(struct intel_plane_state *plane_state)
>>  {
>>  	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
>>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>> @@ -16639,7 +16066,7 @@ static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
>>  	return 0;
>>  }
>>  
>> -static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
>> +void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
>>  {
>>  	struct i915_vma *vma;
>>  
>> @@ -16875,13 +16302,6 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
>>  	}
>>  }
>>  
>> -static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
>> -					      u32 format, u64 modifier)
>> -{
>> -	return modifier == DRM_FORMAT_MOD_LINEAR &&
>> -		format == DRM_FORMAT_ARGB8888;
>> -}
>> -
>>  static const struct drm_plane_funcs i965_plane_funcs = {
>>  	.update_plane = drm_atomic_helper_update_plane,
>>  	.disable_plane = drm_atomic_helper_disable_plane,
>> @@ -16900,142 +16320,6 @@ static const struct drm_plane_funcs i8xx_plane_funcs = {
>>  	.format_mod_supported = i8xx_plane_format_mod_supported,
>>  };
>>  
>> -static int
>> -intel_legacy_cursor_update(struct drm_plane *_plane,
>> -			   struct drm_crtc *_crtc,
>> -			   struct drm_framebuffer *fb,
>> -			   int crtc_x, int crtc_y,
>> -			   unsigned int crtc_w, unsigned int crtc_h,
>> -			   u32 src_x, u32 src_y,
>> -			   u32 src_w, u32 src_h,
>> -			   struct drm_modeset_acquire_ctx *ctx)
>> -{
>> -	struct intel_plane *plane = to_intel_plane(_plane);
>> -	struct intel_crtc *crtc = to_intel_crtc(_crtc);
>> -	struct intel_plane_state *old_plane_state =
>> -		to_intel_plane_state(plane->base.state);
>> -	struct intel_plane_state *new_plane_state;
>> -	struct intel_crtc_state *crtc_state =
>> -		to_intel_crtc_state(crtc->base.state);
>> -	struct intel_crtc_state *new_crtc_state;
>> -	int ret;
>> -
>> -	/*
>> -	 * When crtc is inactive or there is a modeset pending,
>> -	 * wait for it to complete in the slowpath
>> -	 *
>> -	 * FIXME bigjoiner fastpath would be good
>> -	 */
>> -	if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
>> -	    crtc_state->update_pipe || crtc_state->bigjoiner)
>> -		goto slow;
>> -
>> -	/*
>> -	 * Don't do an async update if there is an outstanding commit modifying
>> -	 * the plane.  This prevents our async update's changes from getting
>> -	 * overridden by a previous synchronous update's state.
>> -	 */
>> -	if (old_plane_state->uapi.commit &&
>> -	    !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
>> -		goto slow;
>> -
>> -	/*
>> -	 * If any parameters change that may affect watermarks,
>> -	 * take the slowpath. Only changing fb or position should be
>> -	 * in the fastpath.
>> -	 */
>> -	if (old_plane_state->uapi.crtc != &crtc->base ||
>> -	    old_plane_state->uapi.src_w != src_w ||
>> -	    old_plane_state->uapi.src_h != src_h ||
>> -	    old_plane_state->uapi.crtc_w != crtc_w ||
>> -	    old_plane_state->uapi.crtc_h != crtc_h ||
>> -	    !old_plane_state->uapi.fb != !fb)
>> -		goto slow;
>> -
>> -	new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
>> -	if (!new_plane_state)
>> -		return -ENOMEM;
>> -
>> -	new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
>> -	if (!new_crtc_state) {
>> -		ret = -ENOMEM;
>> -		goto out_free;
>> -	}
>> -
>> -	drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
>> -
>> -	new_plane_state->uapi.src_x = src_x;
>> -	new_plane_state->uapi.src_y = src_y;
>> -	new_plane_state->uapi.src_w = src_w;
>> -	new_plane_state->uapi.src_h = src_h;
>> -	new_plane_state->uapi.crtc_x = crtc_x;
>> -	new_plane_state->uapi.crtc_y = crtc_y;
>> -	new_plane_state->uapi.crtc_w = crtc_w;
>> -	new_plane_state->uapi.crtc_h = crtc_h;
>> -
>> -	intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
>> -
>> -	ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
>> -						  old_plane_state, new_plane_state);
>> -	if (ret)
>> -		goto out_free;
>> -
>> -	ret = intel_plane_pin_fb(new_plane_state);
>> -	if (ret)
>> -		goto out_free;
>> -
>> -	intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
>> -				ORIGIN_FLIP);
>> -	intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
>> -				to_intel_frontbuffer(new_plane_state->hw.fb),
>> -				plane->frontbuffer_bit);
>> -
>> -	/* Swap plane state */
>> -	plane->base.state = &new_plane_state->uapi;
>> -
>> -	/*
>> -	 * We cannot swap crtc_state as it may be in use by an atomic commit or
>> -	 * page flip that's running simultaneously. If we swap crtc_state and
>> -	 * destroy the old state, we will cause a use-after-free there.
>> -	 *
>> -	 * Only update active_planes, which is needed for our internal
>> -	 * bookkeeping. Either value will do the right thing when updating
>> -	 * planes atomically. If the cursor was part of the atomic update then
>> -	 * we would have taken the slowpath.
>> -	 */
>> -	crtc_state->active_planes = new_crtc_state->active_planes;
>> -
>> -	if (new_plane_state->uapi.visible)
>> -		intel_update_plane(plane, crtc_state, new_plane_state);
>> -	else
>> -		intel_disable_plane(plane, crtc_state);
>> -
>> -	intel_plane_unpin_fb(old_plane_state);
>> -
>> -out_free:
>> -	if (new_crtc_state)
>> -		intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
>> -	if (ret)
>> -		intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
>> -	else
>> -		intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
>> -	return ret;
>> -
>> -slow:
>> -	return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
>> -					      crtc_x, crtc_y, crtc_w, crtc_h,
>> -					      src_x, src_y, src_w, src_h, ctx);
>> -}
>> -
>> -static const struct drm_plane_funcs intel_cursor_plane_funcs = {
>> -	.update_plane = intel_legacy_cursor_update,
>> -	.disable_plane = drm_atomic_helper_disable_plane,
>> -	.destroy = intel_plane_destroy,
>> -	.atomic_duplicate_state = intel_plane_duplicate_state,
>> -	.atomic_destroy_state = intel_plane_destroy_state,
>> -	.format_mod_supported = intel_cursor_format_mod_supported,
>> -};
>> -
>>  static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
>>  			       enum i9xx_plane_id i9xx_plane)
>>  {
>> @@ -17187,74 +16471,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>>  	return ERR_PTR(ret);
>>  }
>>  
>> -static struct intel_plane *
>> -intel_cursor_plane_create(struct drm_i915_private *dev_priv,
>> -			  enum pipe pipe)
>> -{
>> -	struct intel_plane *cursor;
>> -	int ret, zpos;
>> -
>> -	cursor = intel_plane_alloc();
>> -	if (IS_ERR(cursor))
>> -		return cursor;
>> -
>> -	cursor->pipe = pipe;
>> -	cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
>> -	cursor->id = PLANE_CURSOR;
>> -	cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
>> -
>> -	if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
>> -		cursor->max_stride = i845_cursor_max_stride;
>> -		cursor->update_plane = i845_update_cursor;
>> -		cursor->disable_plane = i845_disable_cursor;
>> -		cursor->get_hw_state = i845_cursor_get_hw_state;
>> -		cursor->check_plane = i845_check_cursor;
>> -	} else {
>> -		cursor->max_stride = i9xx_cursor_max_stride;
>> -		cursor->update_plane = i9xx_update_cursor;
>> -		cursor->disable_plane = i9xx_disable_cursor;
>> -		cursor->get_hw_state = i9xx_cursor_get_hw_state;
>> -		cursor->check_plane = i9xx_check_cursor;
>> -	}
>> -
>> -	cursor->cursor.base = ~0;
>> -	cursor->cursor.cntl = ~0;
>> -
>> -	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
>> -		cursor->cursor.size = ~0;
>> -
>> -	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
>> -				       0, &intel_cursor_plane_funcs,
>> -				       intel_cursor_formats,
>> -				       ARRAY_SIZE(intel_cursor_formats),
>> -				       cursor_format_modifiers,
>> -				       DRM_PLANE_TYPE_CURSOR,
>> -				       "cursor %c", pipe_name(pipe));
>> -	if (ret)
>> -		goto fail;
>> -
>> -	if (INTEL_GEN(dev_priv) >= 4)
>> -		drm_plane_create_rotation_property(&cursor->base,
>> -						   DRM_MODE_ROTATE_0,
>> -						   DRM_MODE_ROTATE_0 |
>> -						   DRM_MODE_ROTATE_180);
>> -
>> -	zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
>> -	drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
>> -
>> -	if (INTEL_GEN(dev_priv) >= 12)
>> -		drm_plane_enable_fb_damage_clips(&cursor->base);
>> -
>> -	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
>> -
>> -	return cursor;
>> -
>> -fail:
>> -	intel_plane_free(cursor);
>> -
>> -	return ERR_PTR(ret);
>> -}
>> -
>>  static int intel_crtc_late_register(struct drm_crtc *crtc)
>>  {
>>  	intel_crtc_debugfs_add(crtc);
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
>> index a5771bfecba6..f0a5bf69656f 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display.h
>> @@ -647,6 +647,18 @@ bool
>>  intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
>>  				    uint64_t modifier);
>>  
>> +int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
>> +u32 intel_plane_compute_aligned_offset(int *x, int *y,
>> +				       const struct intel_plane_state *state,
>> +				       int color_plane);
>> +int intel_plane_pin_fb(struct intel_plane_state *plane_state);
>> +void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
>> +
>> +/* cursor */
>> +struct intel_plane *
>> +intel_cursor_plane_create(struct drm_i915_private *dev_priv,
>> +			  enum pipe pipe);
>> +
>>  /* modesetting */
>>  void intel_modeset_init_hw(struct drm_i915_private *i915);
>>  int intel_modeset_init_noirq(struct drm_i915_private *i915);
>> -- 
>> 2.27.0
>> 
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c
  2020-12-10 16:12     ` Jani Nikula
@ 2020-12-10 16:17       ` Daniel Vetter
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Vetter @ 2020-12-10 16:17 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 5:12 PM Jani Nikula <jani.nikula@linux.intel.com> wrote:
>
> On Thu, 10 Dec 2020, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > On Thu, Dec 10, 2020 at 02:17:50PM +1000, Dave Airlie wrote:
> >> From: Dave Airlie <airlied@redhat.com>
> >>
> >> This file is a monster, let's start simple, the cursor plane code
> >> seems pretty standalone, and splits out easily enough.
> >>
> >> Signed-off-by: Dave Airlie <airlied@redhat.com>
> >> ---
> >>  drivers/gpu/drm/i915/Makefile                |   1 +
> >>  drivers/gpu/drm/i915/display/intel_cursor.c  | 805 +++++++++++++++++++
> >>  drivers/gpu/drm/i915/display/intel_display.c | 796 +-----------------
> >>  drivers/gpu/drm/i915/display/intel_display.h |  12 +
> >
> > I would just add the intel_cursor.h for this. intel_display.h is an
> > even bigger mess than intel_display.c, and causing no end of redundant
> > rebuilds. The smaller we can make it the better IMO.
>
> Separate header for each .c is where we've been heading since we started
> refactoring the driver to multiple subdirs instead of the flat
> structure, and started chopping up files as a consequence.

Yeah +1 on separate headers. It's mildly more pain for the splitting,
but eventually it allows us to move the structs together with the
functions and actually untangle the spaghetti instead of just putting
it over a few more plates.
-Daniel

> Also, please prefix the functions in intel_foo.[ch] with
> intel_foo_. This is also where we've been heading for a while now.
>
> BR,
> Jani.
>
>
>
> >
> > Looks like a mechanical move, and seems to match my attempt at it so
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> >>  4 files changed, 824 insertions(+), 790 deletions(-)
> >>  create mode 100644 drivers/gpu/drm/i915/display/intel_cursor.c
> >>
> >> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> >> index e5574e506a5c..98a35b939052 100644
> >> --- a/drivers/gpu/drm/i915/Makefile
> >> +++ b/drivers/gpu/drm/i915/Makefile
> >> @@ -197,6 +197,7 @@ i915-y += \
> >>      display/intel_combo_phy.o \
> >>      display/intel_connector.o \
> >>      display/intel_csr.o \
> >> +    display/intel_cursor.o \
> >>      display/intel_display.o \
> >>      display/intel_display_power.o \
> >>      display/intel_dpio_phy.o \
> >> diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
> >> new file mode 100644
> >> index 000000000000..87a7a74a25ac
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/i915/display/intel_cursor.c
> >> @@ -0,0 +1,805 @@
> >> +// SPDX-License-Identifier: MIT
> >> +/*
> >> + * Copyright © 2020 Intel Corporation
> >> + */
> >> +#include <linux/kernel.h>
> >> +
> >> +#include <drm/drm_atomic_helper.h>
> >> +#include <drm/drm_atomic_uapi.h>
> >> +#include <drm/drm_damage_helper.h>
> >> +#include <drm/drm_plane_helper.h>
> >> +#include <drm/drm_fourcc.h>
> >> +
> >> +#include "intel_atomic.h"
> >> +#include "intel_atomic_plane.h"
> >> +#include "intel_display_types.h"
> >> +#include "intel_display.h"
> >> +
> >> +#include "intel_frontbuffer.h"
> >> +#include "intel_pm.h"
> >> +#include "intel_psr.h"
> >> +#include "intel_sprite.h"
> >> +
> >> +/* Cursor formats */
> >> +static const u32 intel_cursor_formats[] = {
> >> +    DRM_FORMAT_ARGB8888,
> >> +};
> >> +
> >> +static const u64 cursor_format_modifiers[] = {
> >> +    DRM_FORMAT_MOD_LINEAR,
> >> +    DRM_FORMAT_MOD_INVALID
> >> +};
> >> +
> >> +static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
> >> +{
> >> +    struct drm_i915_private *dev_priv =
> >> +            to_i915(plane_state->uapi.plane->dev);
> >> +    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> +    const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >> +    u32 base;
> >> +
> >> +    if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
> >> +            base = sg_dma_address(obj->mm.pages->sgl);
> >> +    else
> >> +            base = intel_plane_ggtt_offset(plane_state);
> >> +
> >> +    return base + plane_state->color_plane[0].offset;
> >> +}
> >> +
> >> +static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
> >> +{
> >> +    int x = plane_state->uapi.dst.x1;
> >> +    int y = plane_state->uapi.dst.y1;
> >> +    u32 pos = 0;
> >> +
> >> +    if (x < 0) {
> >> +            pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
> >> +            x = -x;
> >> +    }
> >> +    pos |= x << CURSOR_X_SHIFT;
> >> +
> >> +    if (y < 0) {
> >> +            pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
> >> +            y = -y;
> >> +    }
> >> +    pos |= y << CURSOR_Y_SHIFT;
> >> +
> >> +    return pos;
> >> +}
> >> +
> >> +static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
> >> +{
> >> +    const struct drm_mode_config *config =
> >> +            &plane_state->uapi.plane->dev->mode_config;
> >> +    int width = drm_rect_width(&plane_state->uapi.dst);
> >> +    int height = drm_rect_height(&plane_state->uapi.dst);
> >> +
> >> +    return width > 0 && width <= config->cursor_width &&
> >> +            height > 0 && height <= config->cursor_height;
> >> +}
> >> +
> >> +static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
> >> +{
> >> +    struct drm_i915_private *dev_priv =
> >> +            to_i915(plane_state->uapi.plane->dev);
> >> +    unsigned int rotation = plane_state->hw.rotation;
> >> +    int src_x, src_y;
> >> +    u32 offset;
> >> +    int ret;
> >> +
> >> +    ret = intel_plane_compute_gtt(plane_state);
> >> +    if (ret)
> >> +            return ret;
> >> +
> >> +    if (!plane_state->uapi.visible)
> >> +            return 0;
> >> +
> >> +    src_x = plane_state->uapi.src.x1 >> 16;
> >> +    src_y = plane_state->uapi.src.y1 >> 16;
> >> +
> >> +    intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
> >> +    offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
> >> +                                                plane_state, 0);
> >> +
> >> +    if (src_x != 0 || src_y != 0) {
> >> +            drm_dbg_kms(&dev_priv->drm,
> >> +                        "Arbitrary cursor panning not supported\n");
> >> +            return -EINVAL;
> >> +    }
> >> +
> >> +    /*
> >> +     * Put the final coordinates back so that the src
> >> +     * coordinate checks will see the right values.
> >> +     */
> >> +    drm_rect_translate_to(&plane_state->uapi.src,
> >> +                          src_x << 16, src_y << 16);
> >> +
> >> +    /* ILK+ do this automagically in hardware */
> >> +    if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
> >> +            const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> +            int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> >> +            int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
> >> +
> >> +            offset += (src_h * src_w - 1) * fb->format->cpp[0];
> >> +    }
> >> +
> >> +    plane_state->color_plane[0].offset = offset;
> >> +    plane_state->color_plane[0].x = src_x;
> >> +    plane_state->color_plane[0].y = src_y;
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int intel_check_cursor(struct intel_crtc_state *crtc_state,
> >> +                          struct intel_plane_state *plane_state)
> >> +{
> >> +    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> +    struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> >> +    const struct drm_rect src = plane_state->uapi.src;
> >> +    const struct drm_rect dst = plane_state->uapi.dst;
> >> +    int ret;
> >> +
> >> +    if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
> >> +            drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
> >> +            return -EINVAL;
> >> +    }
> >> +
> >> +    ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> >> +                                            DRM_PLANE_HELPER_NO_SCALING,
> >> +                                            DRM_PLANE_HELPER_NO_SCALING,
> >> +                                            true);
> >> +    if (ret)
> >> +            return ret;
> >> +
> >> +    /* Use the unclipped src/dst rectangles, which we program to hw */
> >> +    plane_state->uapi.src = src;
> >> +    plane_state->uapi.dst = dst;
> >> +
> >> +    ret = intel_cursor_check_surface(plane_state);
> >> +    if (ret)
> >> +            return ret;
> >> +
> >> +    if (!plane_state->uapi.visible)
> >> +            return 0;
> >> +
> >> +    ret = intel_plane_check_src_coordinates(plane_state);
> >> +    if (ret)
> >> +            return ret;
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static unsigned int
> >> +i845_cursor_max_stride(struct intel_plane *plane,
> >> +                   u32 pixel_format, u64 modifier,
> >> +                   unsigned int rotation)
> >> +{
> >> +    return 2048;
> >> +}
> >> +
> >> +static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> >> +{
> >> +    u32 cntl = 0;
> >> +
> >> +    if (crtc_state->gamma_enable)
> >> +            cntl |= CURSOR_GAMMA_ENABLE;
> >> +
> >> +    return cntl;
> >> +}
> >> +
> >> +static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
> >> +                       const struct intel_plane_state *plane_state)
> >> +{
> >> +    return CURSOR_ENABLE |
> >> +            CURSOR_FORMAT_ARGB |
> >> +            CURSOR_STRIDE(plane_state->color_plane[0].stride);
> >> +}
> >> +
> >> +static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
> >> +{
> >> +    int width = drm_rect_width(&plane_state->uapi.dst);
> >> +
> >> +    /*
> >> +     * 845g/865g are only limited by the width of their cursors,
> >> +     * the height is arbitrary up to the precision of the register.
> >> +     */
> >> +    return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
> >> +}
> >> +
> >> +static int i845_check_cursor(struct intel_crtc_state *crtc_state,
> >> +                         struct intel_plane_state *plane_state)
> >> +{
> >> +    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> +    struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> >> +    int ret;
> >> +
> >> +    ret = intel_check_cursor(crtc_state, plane_state);
> >> +    if (ret)
> >> +            return ret;
> >> +
> >> +    /* if we want to turn off the cursor ignore width and height */
> >> +    if (!fb)
> >> +            return 0;
> >> +
> >> +    /* Check for which cursor types we support */
> >> +    if (!i845_cursor_size_ok(plane_state)) {
> >> +            drm_dbg_kms(&i915->drm,
> >> +                        "Cursor dimension %dx%d not supported\n",
> >> +                        drm_rect_width(&plane_state->uapi.dst),
> >> +                        drm_rect_height(&plane_state->uapi.dst));
> >> +            return -EINVAL;
> >> +    }
> >> +
> >> +    drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
> >> +                plane_state->color_plane[0].stride != fb->pitches[0]);
> >> +
> >> +    switch (fb->pitches[0]) {
> >> +    case 256:
> >> +    case 512:
> >> +    case 1024:
> >> +    case 2048:
> >> +            break;
> >> +    default:
> >> +             drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
> >> +                         fb->pitches[0]);
> >> +            return -EINVAL;
> >> +    }
> >> +
> >> +    plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static void i845_update_cursor(struct intel_plane *plane,
> >> +                           const struct intel_crtc_state *crtc_state,
> >> +                           const struct intel_plane_state *plane_state)
> >> +{
> >> +    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> +    u32 cntl = 0, base = 0, pos = 0, size = 0;
> >> +    unsigned long irqflags;
> >> +
> >> +    if (plane_state && plane_state->uapi.visible) {
> >> +            unsigned int width = drm_rect_width(&plane_state->uapi.dst);
> >> +            unsigned int height = drm_rect_height(&plane_state->uapi.dst);
> >> +
> >> +            cntl = plane_state->ctl |
> >> +                    i845_cursor_ctl_crtc(crtc_state);
> >> +
> >> +            size = (height << 12) | width;
> >> +
> >> +            base = intel_cursor_base(plane_state);
> >> +            pos = intel_cursor_position(plane_state);
> >> +    }
> >> +
> >> +    spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> >> +
> >> +    /* On these chipsets we can only modify the base/size/stride
> >> +     * whilst the cursor is disabled.
> >> +     */
> >> +    if (plane->cursor.base != base ||
> >> +        plane->cursor.size != size ||
> >> +        plane->cursor.cntl != cntl) {
> >> +            intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
> >> +            intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
> >> +            intel_de_write_fw(dev_priv, CURSIZE, size);
> >> +            intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> >> +            intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
> >> +
> >> +            plane->cursor.base = base;
> >> +            plane->cursor.size = size;
> >> +            plane->cursor.cntl = cntl;
> >> +    } else {
> >> +            intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> >> +    }
> >> +
> >> +    spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> >> +}
> >> +
> >> +static void i845_disable_cursor(struct intel_plane *plane,
> >> +                            const struct intel_crtc_state *crtc_state)
> >> +{
> >> +    i845_update_cursor(plane, crtc_state, NULL);
> >> +}
> >> +
> >> +static bool i845_cursor_get_hw_state(struct intel_plane *plane,
> >> +                                 enum pipe *pipe)
> >> +{
> >> +    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> +    enum intel_display_power_domain power_domain;
> >> +    intel_wakeref_t wakeref;
> >> +    bool ret;
> >> +
> >> +    power_domain = POWER_DOMAIN_PIPE(PIPE_A);
> >> +    wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> >> +    if (!wakeref)
> >> +            return false;
> >> +
> >> +    ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
> >> +
> >> +    *pipe = PIPE_A;
> >> +
> >> +    intel_display_power_put(dev_priv, power_domain, wakeref);
> >> +
> >> +    return ret;
> >> +}
> >> +
> >> +static unsigned int
> >> +i9xx_cursor_max_stride(struct intel_plane *plane,
> >> +                   u32 pixel_format, u64 modifier,
> >> +                   unsigned int rotation)
> >> +{
> >> +    return plane->base.dev->mode_config.cursor_width * 4;
> >> +}
> >> +
> >> +static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> >> +{
> >> +    struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> >> +    struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> >> +    u32 cntl = 0;
> >> +
> >> +    if (INTEL_GEN(dev_priv) >= 11)
> >> +            return cntl;
> >> +
> >> +    if (crtc_state->gamma_enable)
> >> +            cntl = MCURSOR_GAMMA_ENABLE;
> >> +
> >> +    if (crtc_state->csc_enable)
> >> +            cntl |= MCURSOR_PIPE_CSC_ENABLE;
> >> +
> >> +    if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
> >> +            cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
> >> +
> >> +    return cntl;
> >> +}
> >> +
> >> +static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
> >> +                       const struct intel_plane_state *plane_state)
> >> +{
> >> +    struct drm_i915_private *dev_priv =
> >> +            to_i915(plane_state->uapi.plane->dev);
> >> +    u32 cntl = 0;
> >> +
> >> +    if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> >> +            cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
> >> +
> >> +    switch (drm_rect_width(&plane_state->uapi.dst)) {
> >> +    case 64:
> >> +            cntl |= MCURSOR_MODE_64_ARGB_AX;
> >> +            break;
> >> +    case 128:
> >> +            cntl |= MCURSOR_MODE_128_ARGB_AX;
> >> +            break;
> >> +    case 256:
> >> +            cntl |= MCURSOR_MODE_256_ARGB_AX;
> >> +            break;
> >> +    default:
> >> +            MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
> >> +            return 0;
> >> +    }
> >> +
> >> +    if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
> >> +            cntl |= MCURSOR_ROTATE_180;
> >> +
> >> +    return cntl;
> >> +}
> >> +
> >> +static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
> >> +{
> >> +    struct drm_i915_private *dev_priv =
> >> +            to_i915(plane_state->uapi.plane->dev);
> >> +    int width = drm_rect_width(&plane_state->uapi.dst);
> >> +    int height = drm_rect_height(&plane_state->uapi.dst);
> >> +
> >> +    if (!intel_cursor_size_ok(plane_state))
> >> +            return false;
> >> +
> >> +    /* Cursor width is limited to a few power-of-two sizes */
> >> +    switch (width) {
> >> +    case 256:
> >> +    case 128:
> >> +    case 64:
> >> +            break;
> >> +    default:
> >> +            return false;
> >> +    }
> >> +
> >> +    /*
> >> +     * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
> >> +     * height from 8 lines up to the cursor width, when the
> >> +     * cursor is not rotated. Everything else requires square
> >> +     * cursors.
> >> +     */
> >> +    if (HAS_CUR_FBC(dev_priv) &&
> >> +        plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
> >> +            if (height < 8 || height > width)
> >> +                    return false;
> >> +    } else {
> >> +            if (height != width)
> >> +                    return false;
> >> +    }
> >> +
> >> +    return true;
> >> +}
> >> +
> >> +static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
> >> +                         struct intel_plane_state *plane_state)
> >> +{
> >> +    struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> >> +    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> +    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> +    enum pipe pipe = plane->pipe;
> >> +    int ret;
> >> +
> >> +    ret = intel_check_cursor(crtc_state, plane_state);
> >> +    if (ret)
> >> +            return ret;
> >> +
> >> +    /* if we want to turn off the cursor ignore width and height */
> >> +    if (!fb)
> >> +            return 0;
> >> +
> >> +    /* Check for which cursor types we support */
> >> +    if (!i9xx_cursor_size_ok(plane_state)) {
> >> +            drm_dbg(&dev_priv->drm,
> >> +                    "Cursor dimension %dx%d not supported\n",
> >> +                    drm_rect_width(&plane_state->uapi.dst),
> >> +                    drm_rect_height(&plane_state->uapi.dst));
> >> +            return -EINVAL;
> >> +    }
> >> +
> >> +    drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
> >> +                plane_state->color_plane[0].stride != fb->pitches[0]);
> >> +
> >> +    if (fb->pitches[0] !=
> >> +        drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
> >> +            drm_dbg_kms(&dev_priv->drm,
> >> +                        "Invalid cursor stride (%u) (cursor width %d)\n",
> >> +                        fb->pitches[0],
> >> +                        drm_rect_width(&plane_state->uapi.dst));
> >> +            return -EINVAL;
> >> +    }
> >> +
> >> +    /*
> >> +     * There's something wrong with the cursor on CHV pipe C.
> >> +     * If it straddles the left edge of the screen then
> >> +     * moving it away from the edge or disabling it often
> >> +     * results in a pipe underrun, and often that can lead to
> >> +     * dead pipe (constant underrun reported, and it scans
> >> +     * out just a solid color). To recover from that, the
> >> +     * display power well must be turned off and on again.
> >> +     * Refuse the put the cursor into that compromised position.
> >> +     */
> >> +    if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
> >> +        plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
> >> +            drm_dbg_kms(&dev_priv->drm,
> >> +                        "CHV cursor C not allowed to straddle the left screen edge\n");
> >> +            return -EINVAL;
> >> +    }
> >> +
> >> +    plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static void i9xx_update_cursor(struct intel_plane *plane,
> >> +                           const struct intel_crtc_state *crtc_state,
> >> +                           const struct intel_plane_state *plane_state)
> >> +{
> >> +    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> +    enum pipe pipe = plane->pipe;
> >> +    u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
> >> +    unsigned long irqflags;
> >> +
> >> +    if (plane_state && plane_state->uapi.visible) {
> >> +            unsigned width = drm_rect_width(&plane_state->uapi.dst);
> >> +            unsigned height = drm_rect_height(&plane_state->uapi.dst);
> >> +
> >> +            cntl = plane_state->ctl |
> >> +                    i9xx_cursor_ctl_crtc(crtc_state);
> >> +
> >> +            if (width != height)
> >> +                    fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
> >> +
> >> +            base = intel_cursor_base(plane_state);
> >> +            pos = intel_cursor_position(plane_state);
> >> +    }
> >> +
> >> +    spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> >> +
> >> +    /*
> >> +     * On some platforms writing CURCNTR first will also
> >> +     * cause CURPOS to be armed by the CURBASE write.
> >> +     * Without the CURCNTR write the CURPOS write would
> >> +     * arm itself. Thus we always update CURCNTR before
> >> +     * CURPOS.
> >> +     *
> >> +     * On other platforms CURPOS always requires the
> >> +     * CURBASE write to arm the update. Additonally
> >> +     * a write to any of the cursor register will cancel
> >> +     * an already armed cursor update. Thus leaving out
> >> +     * the CURBASE write after CURPOS could lead to a
> >> +     * cursor that doesn't appear to move, or even change
> >> +     * shape. Thus we always write CURBASE.
> >> +     *
> >> +     * The other registers are armed by by the CURBASE write
> >> +     * except when the plane is getting enabled at which time
> >> +     * the CURCNTR write arms the update.
> >> +     */
> >> +
> >> +    if (INTEL_GEN(dev_priv) >= 9)
> >> +            skl_write_cursor_wm(plane, crtc_state);
> >> +
> >> +    if (!intel_crtc_needs_modeset(crtc_state))
> >> +            intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
> >> +
> >> +    if (plane->cursor.base != base ||
> >> +        plane->cursor.size != fbc_ctl ||
> >> +        plane->cursor.cntl != cntl) {
> >> +            if (HAS_CUR_FBC(dev_priv))
> >> +                    intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
> >> +                                      fbc_ctl);
> >> +            intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
> >> +            intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> >> +            intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> >> +
> >> +            plane->cursor.base = base;
> >> +            plane->cursor.size = fbc_ctl;
> >> +            plane->cursor.cntl = cntl;
> >> +    } else {
> >> +            intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> >> +            intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> >> +    }
> >> +
> >> +    spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> >> +}
> >> +
> >> +static void i9xx_disable_cursor(struct intel_plane *plane,
> >> +                            const struct intel_crtc_state *crtc_state)
> >> +{
> >> +    i9xx_update_cursor(plane, crtc_state, NULL);
> >> +}
> >> +
> >> +static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
> >> +                                 enum pipe *pipe)
> >> +{
> >> +    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> +    enum intel_display_power_domain power_domain;
> >> +    intel_wakeref_t wakeref;
> >> +    bool ret;
> >> +    u32 val;
> >> +
> >> +    /*
> >> +     * Not 100% correct for planes that can move between pipes,
> >> +     * but that's only the case for gen2-3 which don't have any
> >> +     * display power wells.
> >> +     */
> >> +    power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> >> +    wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> >> +    if (!wakeref)
> >> +            return false;
> >> +
> >> +    val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
> >> +
> >> +    ret = val & MCURSOR_MODE;
> >> +
> >> +    if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> >> +            *pipe = plane->pipe;
> >> +    else
> >> +            *pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
> >> +                    MCURSOR_PIPE_SELECT_SHIFT;
> >> +
> >> +    intel_display_power_put(dev_priv, power_domain, wakeref);
> >> +
> >> +    return ret;
> >> +}
> >> +
> >> +static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
> >> +                                          u32 format, u64 modifier)
> >> +{
> >> +    return modifier == DRM_FORMAT_MOD_LINEAR &&
> >> +            format == DRM_FORMAT_ARGB8888;
> >> +}
> >> +
> >> +static int
> >> +intel_legacy_cursor_update(struct drm_plane *_plane,
> >> +                       struct drm_crtc *_crtc,
> >> +                       struct drm_framebuffer *fb,
> >> +                       int crtc_x, int crtc_y,
> >> +                       unsigned int crtc_w, unsigned int crtc_h,
> >> +                       u32 src_x, u32 src_y,
> >> +                       u32 src_w, u32 src_h,
> >> +                       struct drm_modeset_acquire_ctx *ctx)
> >> +{
> >> +    struct intel_plane *plane = to_intel_plane(_plane);
> >> +    struct intel_crtc *crtc = to_intel_crtc(_crtc);
> >> +    struct intel_plane_state *old_plane_state =
> >> +            to_intel_plane_state(plane->base.state);
> >> +    struct intel_plane_state *new_plane_state;
> >> +    struct intel_crtc_state *crtc_state =
> >> +            to_intel_crtc_state(crtc->base.state);
> >> +    struct intel_crtc_state *new_crtc_state;
> >> +    int ret;
> >> +
> >> +    /*
> >> +     * When crtc is inactive or there is a modeset pending,
> >> +     * wait for it to complete in the slowpath
> >> +     *
> >> +     * FIXME bigjoiner fastpath would be good
> >> +     */
> >> +    if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
> >> +        crtc_state->update_pipe || crtc_state->bigjoiner)
> >> +            goto slow;
> >> +
> >> +    /*
> >> +     * Don't do an async update if there is an outstanding commit modifying
> >> +     * the plane.  This prevents our async update's changes from getting
> >> +     * overridden by a previous synchronous update's state.
> >> +     */
> >> +    if (old_plane_state->uapi.commit &&
> >> +        !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
> >> +            goto slow;
> >> +
> >> +    /*
> >> +     * If any parameters change that may affect watermarks,
> >> +     * take the slowpath. Only changing fb or position should be
> >> +     * in the fastpath.
> >> +     */
> >> +    if (old_plane_state->uapi.crtc != &crtc->base ||
> >> +        old_plane_state->uapi.src_w != src_w ||
> >> +        old_plane_state->uapi.src_h != src_h ||
> >> +        old_plane_state->uapi.crtc_w != crtc_w ||
> >> +        old_plane_state->uapi.crtc_h != crtc_h ||
> >> +        !old_plane_state->uapi.fb != !fb)
> >> +            goto slow;
> >> +
> >> +    new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
> >> +    if (!new_plane_state)
> >> +            return -ENOMEM;
> >> +
> >> +    new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
> >> +    if (!new_crtc_state) {
> >> +            ret = -ENOMEM;
> >> +            goto out_free;
> >> +    }
> >> +
> >> +    drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
> >> +
> >> +    new_plane_state->uapi.src_x = src_x;
> >> +    new_plane_state->uapi.src_y = src_y;
> >> +    new_plane_state->uapi.src_w = src_w;
> >> +    new_plane_state->uapi.src_h = src_h;
> >> +    new_plane_state->uapi.crtc_x = crtc_x;
> >> +    new_plane_state->uapi.crtc_y = crtc_y;
> >> +    new_plane_state->uapi.crtc_w = crtc_w;
> >> +    new_plane_state->uapi.crtc_h = crtc_h;
> >> +
> >> +    intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
> >> +
> >> +    ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
> >> +                                              old_plane_state, new_plane_state);
> >> +    if (ret)
> >> +            goto out_free;
> >> +
> >> +    ret = intel_plane_pin_fb(new_plane_state);
> >> +    if (ret)
> >> +            goto out_free;
> >> +
> >> +    intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
> >> +                            ORIGIN_FLIP);
> >> +    intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
> >> +                            to_intel_frontbuffer(new_plane_state->hw.fb),
> >> +                            plane->frontbuffer_bit);
> >> +
> >> +    /* Swap plane state */
> >> +    plane->base.state = &new_plane_state->uapi;
> >> +
> >> +    /*
> >> +     * We cannot swap crtc_state as it may be in use by an atomic commit or
> >> +     * page flip that's running simultaneously. If we swap crtc_state and
> >> +     * destroy the old state, we will cause a use-after-free there.
> >> +     *
> >> +     * Only update active_planes, which is needed for our internal
> >> +     * bookkeeping. Either value will do the right thing when updating
> >> +     * planes atomically. If the cursor was part of the atomic update then
> >> +     * we would have taken the slowpath.
> >> +     */
> >> +    crtc_state->active_planes = new_crtc_state->active_planes;
> >> +
> >> +    if (new_plane_state->uapi.visible)
> >> +            intel_update_plane(plane, crtc_state, new_plane_state);
> >> +    else
> >> +            intel_disable_plane(plane, crtc_state);
> >> +
> >> +    intel_plane_unpin_fb(old_plane_state);
> >> +
> >> +out_free:
> >> +    if (new_crtc_state)
> >> +            intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
> >> +    if (ret)
> >> +            intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
> >> +    else
> >> +            intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
> >> +    return ret;
> >> +
> >> +slow:
> >> +    return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
> >> +                                          crtc_x, crtc_y, crtc_w, crtc_h,
> >> +                                          src_x, src_y, src_w, src_h, ctx);
> >> +}
> >> +
> >> +static const struct drm_plane_funcs intel_cursor_plane_funcs = {
> >> +    .update_plane = intel_legacy_cursor_update,
> >> +    .disable_plane = drm_atomic_helper_disable_plane,
> >> +    .destroy = intel_plane_destroy,
> >> +    .atomic_duplicate_state = intel_plane_duplicate_state,
> >> +    .atomic_destroy_state = intel_plane_destroy_state,
> >> +    .format_mod_supported = intel_cursor_format_mod_supported,
> >> +};
> >> +
> >> +struct intel_plane *
> >> +intel_cursor_plane_create(struct drm_i915_private *dev_priv,
> >> +                      enum pipe pipe)
> >> +{
> >> +    struct intel_plane *cursor;
> >> +    int ret, zpos;
> >> +
> >> +    cursor = intel_plane_alloc();
> >> +    if (IS_ERR(cursor))
> >> +            return cursor;
> >> +
> >> +    cursor->pipe = pipe;
> >> +    cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
> >> +    cursor->id = PLANE_CURSOR;
> >> +    cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
> >> +
> >> +    if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
> >> +            cursor->max_stride = i845_cursor_max_stride;
> >> +            cursor->update_plane = i845_update_cursor;
> >> +            cursor->disable_plane = i845_disable_cursor;
> >> +            cursor->get_hw_state = i845_cursor_get_hw_state;
> >> +            cursor->check_plane = i845_check_cursor;
> >> +    } else {
> >> +            cursor->max_stride = i9xx_cursor_max_stride;
> >> +            cursor->update_plane = i9xx_update_cursor;
> >> +            cursor->disable_plane = i9xx_disable_cursor;
> >> +            cursor->get_hw_state = i9xx_cursor_get_hw_state;
> >> +            cursor->check_plane = i9xx_check_cursor;
> >> +    }
> >> +
> >> +    cursor->cursor.base = ~0;
> >> +    cursor->cursor.cntl = ~0;
> >> +
> >> +    if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
> >> +            cursor->cursor.size = ~0;
> >> +
> >> +    ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
> >> +                                   0, &intel_cursor_plane_funcs,
> >> +                                   intel_cursor_formats,
> >> +                                   ARRAY_SIZE(intel_cursor_formats),
> >> +                                   cursor_format_modifiers,
> >> +                                   DRM_PLANE_TYPE_CURSOR,
> >> +                                   "cursor %c", pipe_name(pipe));
> >> +    if (ret)
> >> +            goto fail;
> >> +
> >> +    if (INTEL_GEN(dev_priv) >= 4)
> >> +            drm_plane_create_rotation_property(&cursor->base,
> >> +                                               DRM_MODE_ROTATE_0,
> >> +                                               DRM_MODE_ROTATE_0 |
> >> +                                               DRM_MODE_ROTATE_180);
> >> +
> >> +    zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
> >> +    drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
> >> +
> >> +    if (INTEL_GEN(dev_priv) >= 12)
> >> +            drm_plane_enable_fb_damage_clips(&cursor->base);
> >> +
> >> +    drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
> >> +
> >> +    return cursor;
> >> +
> >> +fail:
> >> +    intel_plane_free(cursor);
> >> +
> >> +    return ERR_PTR(ret);
> >> +}
> >> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> >> index 79d7479beed2..722a1cf61941 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> >> @@ -137,16 +137,6 @@ static const u64 i9xx_format_modifiers[] = {
> >>      DRM_FORMAT_MOD_INVALID
> >>  };
> >>
> >> -/* Cursor formats */
> >> -static const u32 intel_cursor_formats[] = {
> >> -    DRM_FORMAT_ARGB8888,
> >> -};
> >> -
> >> -static const u64 cursor_format_modifiers[] = {
> >> -    DRM_FORMAT_MOD_LINEAR,
> >> -    DRM_FORMAT_MOD_INVALID
> >> -};
> >> -
> >>  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
> >>                              struct intel_crtc_state *pipe_config);
> >>  static void ilk_pch_clock_get(struct intel_crtc *crtc,
> >> @@ -2528,9 +2518,9 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,
> >>      return offset_aligned;
> >>  }
> >>
> >> -static u32 intel_plane_compute_aligned_offset(int *x, int *y,
> >> -                                          const struct intel_plane_state *state,
> >> -                                          int color_plane)
> >> +u32 intel_plane_compute_aligned_offset(int *x, int *y,
> >> +                                   const struct intel_plane_state *state,
> >> +                                   int color_plane)
> >>  {
> >>      struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane);
> >>      struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
> >> @@ -3267,7 +3257,7 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)
> >>      }
> >>  }
> >>
> >> -static int
> >> +int
> >>  intel_plane_compute_gtt(struct intel_plane_state *plane_state)
> >>  {
> >>      const struct intel_framebuffer *fb =
> >> @@ -11536,569 +11526,6 @@ static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state)
> >>      return true;
> >>  }
> >>
> >> -static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
> >> -{
> >> -    struct drm_i915_private *dev_priv =
> >> -            to_i915(plane_state->uapi.plane->dev);
> >> -    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> -    const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >> -    u32 base;
> >> -
> >> -    if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
> >> -            base = sg_dma_address(obj->mm.pages->sgl);
> >> -    else
> >> -            base = intel_plane_ggtt_offset(plane_state);
> >> -
> >> -    return base + plane_state->color_plane[0].offset;
> >> -}
> >> -
> >> -static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
> >> -{
> >> -    int x = plane_state->uapi.dst.x1;
> >> -    int y = plane_state->uapi.dst.y1;
> >> -    u32 pos = 0;
> >> -
> >> -    if (x < 0) {
> >> -            pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
> >> -            x = -x;
> >> -    }
> >> -    pos |= x << CURSOR_X_SHIFT;
> >> -
> >> -    if (y < 0) {
> >> -            pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
> >> -            y = -y;
> >> -    }
> >> -    pos |= y << CURSOR_Y_SHIFT;
> >> -
> >> -    return pos;
> >> -}
> >> -
> >> -static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
> >> -{
> >> -    const struct drm_mode_config *config =
> >> -            &plane_state->uapi.plane->dev->mode_config;
> >> -    int width = drm_rect_width(&plane_state->uapi.dst);
> >> -    int height = drm_rect_height(&plane_state->uapi.dst);
> >> -
> >> -    return width > 0 && width <= config->cursor_width &&
> >> -            height > 0 && height <= config->cursor_height;
> >> -}
> >> -
> >> -static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
> >> -{
> >> -    struct drm_i915_private *dev_priv =
> >> -            to_i915(plane_state->uapi.plane->dev);
> >> -    unsigned int rotation = plane_state->hw.rotation;
> >> -    int src_x, src_y;
> >> -    u32 offset;
> >> -    int ret;
> >> -
> >> -    ret = intel_plane_compute_gtt(plane_state);
> >> -    if (ret)
> >> -            return ret;
> >> -
> >> -    if (!plane_state->uapi.visible)
> >> -            return 0;
> >> -
> >> -    src_x = plane_state->uapi.src.x1 >> 16;
> >> -    src_y = plane_state->uapi.src.y1 >> 16;
> >> -
> >> -    intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
> >> -    offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
> >> -                                                plane_state, 0);
> >> -
> >> -    if (src_x != 0 || src_y != 0) {
> >> -            drm_dbg_kms(&dev_priv->drm,
> >> -                        "Arbitrary cursor panning not supported\n");
> >> -            return -EINVAL;
> >> -    }
> >> -
> >> -    /*
> >> -     * Put the final coordinates back so that the src
> >> -     * coordinate checks will see the right values.
> >> -     */
> >> -    drm_rect_translate_to(&plane_state->uapi.src,
> >> -                          src_x << 16, src_y << 16);
> >> -
> >> -    /* ILK+ do this automagically in hardware */
> >> -    if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
> >> -            const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> -            int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> >> -            int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
> >> -
> >> -            offset += (src_h * src_w - 1) * fb->format->cpp[0];
> >> -    }
> >> -
> >> -    plane_state->color_plane[0].offset = offset;
> >> -    plane_state->color_plane[0].x = src_x;
> >> -    plane_state->color_plane[0].y = src_y;
> >> -
> >> -    return 0;
> >> -}
> >> -
> >> -static int intel_check_cursor(struct intel_crtc_state *crtc_state,
> >> -                          struct intel_plane_state *plane_state)
> >> -{
> >> -    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> -    struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> >> -    const struct drm_rect src = plane_state->uapi.src;
> >> -    const struct drm_rect dst = plane_state->uapi.dst;
> >> -    int ret;
> >> -
> >> -    if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
> >> -            drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
> >> -            return -EINVAL;
> >> -    }
> >> -
> >> -    ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> >> -                                            DRM_PLANE_HELPER_NO_SCALING,
> >> -                                            DRM_PLANE_HELPER_NO_SCALING,
> >> -                                            true);
> >> -    if (ret)
> >> -            return ret;
> >> -
> >> -    /* Use the unclipped src/dst rectangles, which we program to hw */
> >> -    plane_state->uapi.src = src;
> >> -    plane_state->uapi.dst = dst;
> >> -
> >> -    ret = intel_cursor_check_surface(plane_state);
> >> -    if (ret)
> >> -            return ret;
> >> -
> >> -    if (!plane_state->uapi.visible)
> >> -            return 0;
> >> -
> >> -    ret = intel_plane_check_src_coordinates(plane_state);
> >> -    if (ret)
> >> -            return ret;
> >> -
> >> -    return 0;
> >> -}
> >> -
> >> -static unsigned int
> >> -i845_cursor_max_stride(struct intel_plane *plane,
> >> -                   u32 pixel_format, u64 modifier,
> >> -                   unsigned int rotation)
> >> -{
> >> -    return 2048;
> >> -}
> >> -
> >> -static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> >> -{
> >> -    u32 cntl = 0;
> >> -
> >> -    if (crtc_state->gamma_enable)
> >> -            cntl |= CURSOR_GAMMA_ENABLE;
> >> -
> >> -    return cntl;
> >> -}
> >> -
> >> -static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
> >> -                       const struct intel_plane_state *plane_state)
> >> -{
> >> -    return CURSOR_ENABLE |
> >> -            CURSOR_FORMAT_ARGB |
> >> -            CURSOR_STRIDE(plane_state->color_plane[0].stride);
> >> -}
> >> -
> >> -static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
> >> -{
> >> -    int width = drm_rect_width(&plane_state->uapi.dst);
> >> -
> >> -    /*
> >> -     * 845g/865g are only limited by the width of their cursors,
> >> -     * the height is arbitrary up to the precision of the register.
> >> -     */
> >> -    return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
> >> -}
> >> -
> >> -static int i845_check_cursor(struct intel_crtc_state *crtc_state,
> >> -                         struct intel_plane_state *plane_state)
> >> -{
> >> -    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> -    struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
> >> -    int ret;
> >> -
> >> -    ret = intel_check_cursor(crtc_state, plane_state);
> >> -    if (ret)
> >> -            return ret;
> >> -
> >> -    /* if we want to turn off the cursor ignore width and height */
> >> -    if (!fb)
> >> -            return 0;
> >> -
> >> -    /* Check for which cursor types we support */
> >> -    if (!i845_cursor_size_ok(plane_state)) {
> >> -            drm_dbg_kms(&i915->drm,
> >> -                        "Cursor dimension %dx%d not supported\n",
> >> -                        drm_rect_width(&plane_state->uapi.dst),
> >> -                        drm_rect_height(&plane_state->uapi.dst));
> >> -            return -EINVAL;
> >> -    }
> >> -
> >> -    drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
> >> -                plane_state->color_plane[0].stride != fb->pitches[0]);
> >> -
> >> -    switch (fb->pitches[0]) {
> >> -    case 256:
> >> -    case 512:
> >> -    case 1024:
> >> -    case 2048:
> >> -            break;
> >> -    default:
> >> -             drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
> >> -                         fb->pitches[0]);
> >> -            return -EINVAL;
> >> -    }
> >> -
> >> -    plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
> >> -
> >> -    return 0;
> >> -}
> >> -
> >> -static void i845_update_cursor(struct intel_plane *plane,
> >> -                           const struct intel_crtc_state *crtc_state,
> >> -                           const struct intel_plane_state *plane_state)
> >> -{
> >> -    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> -    u32 cntl = 0, base = 0, pos = 0, size = 0;
> >> -    unsigned long irqflags;
> >> -
> >> -    if (plane_state && plane_state->uapi.visible) {
> >> -            unsigned int width = drm_rect_width(&plane_state->uapi.dst);
> >> -            unsigned int height = drm_rect_height(&plane_state->uapi.dst);
> >> -
> >> -            cntl = plane_state->ctl |
> >> -                    i845_cursor_ctl_crtc(crtc_state);
> >> -
> >> -            size = (height << 12) | width;
> >> -
> >> -            base = intel_cursor_base(plane_state);
> >> -            pos = intel_cursor_position(plane_state);
> >> -    }
> >> -
> >> -    spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> >> -
> >> -    /* On these chipsets we can only modify the base/size/stride
> >> -     * whilst the cursor is disabled.
> >> -     */
> >> -    if (plane->cursor.base != base ||
> >> -        plane->cursor.size != size ||
> >> -        plane->cursor.cntl != cntl) {
> >> -            intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
> >> -            intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
> >> -            intel_de_write_fw(dev_priv, CURSIZE, size);
> >> -            intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> >> -            intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
> >> -
> >> -            plane->cursor.base = base;
> >> -            plane->cursor.size = size;
> >> -            plane->cursor.cntl = cntl;
> >> -    } else {
> >> -            intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
> >> -    }
> >> -
> >> -    spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> >> -}
> >> -
> >> -static void i845_disable_cursor(struct intel_plane *plane,
> >> -                            const struct intel_crtc_state *crtc_state)
> >> -{
> >> -    i845_update_cursor(plane, crtc_state, NULL);
> >> -}
> >> -
> >> -static bool i845_cursor_get_hw_state(struct intel_plane *plane,
> >> -                                 enum pipe *pipe)
> >> -{
> >> -    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> -    enum intel_display_power_domain power_domain;
> >> -    intel_wakeref_t wakeref;
> >> -    bool ret;
> >> -
> >> -    power_domain = POWER_DOMAIN_PIPE(PIPE_A);
> >> -    wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> >> -    if (!wakeref)
> >> -            return false;
> >> -
> >> -    ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
> >> -
> >> -    *pipe = PIPE_A;
> >> -
> >> -    intel_display_power_put(dev_priv, power_domain, wakeref);
> >> -
> >> -    return ret;
> >> -}
> >> -
> >> -static unsigned int
> >> -i9xx_cursor_max_stride(struct intel_plane *plane,
> >> -                   u32 pixel_format, u64 modifier,
> >> -                   unsigned int rotation)
> >> -{
> >> -    return plane->base.dev->mode_config.cursor_width * 4;
> >> -}
> >> -
> >> -static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
> >> -{
> >> -    struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> >> -    struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> >> -    u32 cntl = 0;
> >> -
> >> -    if (INTEL_GEN(dev_priv) >= 11)
> >> -            return cntl;
> >> -
> >> -    if (crtc_state->gamma_enable)
> >> -            cntl = MCURSOR_GAMMA_ENABLE;
> >> -
> >> -    if (crtc_state->csc_enable)
> >> -            cntl |= MCURSOR_PIPE_CSC_ENABLE;
> >> -
> >> -    if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
> >> -            cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
> >> -
> >> -    return cntl;
> >> -}
> >> -
> >> -static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
> >> -                       const struct intel_plane_state *plane_state)
> >> -{
> >> -    struct drm_i915_private *dev_priv =
> >> -            to_i915(plane_state->uapi.plane->dev);
> >> -    u32 cntl = 0;
> >> -
> >> -    if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> >> -            cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
> >> -
> >> -    switch (drm_rect_width(&plane_state->uapi.dst)) {
> >> -    case 64:
> >> -            cntl |= MCURSOR_MODE_64_ARGB_AX;
> >> -            break;
> >> -    case 128:
> >> -            cntl |= MCURSOR_MODE_128_ARGB_AX;
> >> -            break;
> >> -    case 256:
> >> -            cntl |= MCURSOR_MODE_256_ARGB_AX;
> >> -            break;
> >> -    default:
> >> -            MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
> >> -            return 0;
> >> -    }
> >> -
> >> -    if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
> >> -            cntl |= MCURSOR_ROTATE_180;
> >> -
> >> -    return cntl;
> >> -}
> >> -
> >> -static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
> >> -{
> >> -    struct drm_i915_private *dev_priv =
> >> -            to_i915(plane_state->uapi.plane->dev);
> >> -    int width = drm_rect_width(&plane_state->uapi.dst);
> >> -    int height = drm_rect_height(&plane_state->uapi.dst);
> >> -
> >> -    if (!intel_cursor_size_ok(plane_state))
> >> -            return false;
> >> -
> >> -    /* Cursor width is limited to a few power-of-two sizes */
> >> -    switch (width) {
> >> -    case 256:
> >> -    case 128:
> >> -    case 64:
> >> -            break;
> >> -    default:
> >> -            return false;
> >> -    }
> >> -
> >> -    /*
> >> -     * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
> >> -     * height from 8 lines up to the cursor width, when the
> >> -     * cursor is not rotated. Everything else requires square
> >> -     * cursors.
> >> -     */
> >> -    if (HAS_CUR_FBC(dev_priv) &&
> >> -        plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
> >> -            if (height < 8 || height > width)
> >> -                    return false;
> >> -    } else {
> >> -            if (height != width)
> >> -                    return false;
> >> -    }
> >> -
> >> -    return true;
> >> -}
> >> -
> >> -static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
> >> -                         struct intel_plane_state *plane_state)
> >> -{
> >> -    struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> >> -    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> -    const struct drm_framebuffer *fb = plane_state->hw.fb;
> >> -    enum pipe pipe = plane->pipe;
> >> -    int ret;
> >> -
> >> -    ret = intel_check_cursor(crtc_state, plane_state);
> >> -    if (ret)
> >> -            return ret;
> >> -
> >> -    /* if we want to turn off the cursor ignore width and height */
> >> -    if (!fb)
> >> -            return 0;
> >> -
> >> -    /* Check for which cursor types we support */
> >> -    if (!i9xx_cursor_size_ok(plane_state)) {
> >> -            drm_dbg(&dev_priv->drm,
> >> -                    "Cursor dimension %dx%d not supported\n",
> >> -                    drm_rect_width(&plane_state->uapi.dst),
> >> -                    drm_rect_height(&plane_state->uapi.dst));
> >> -            return -EINVAL;
> >> -    }
> >> -
> >> -    drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
> >> -                plane_state->color_plane[0].stride != fb->pitches[0]);
> >> -
> >> -    if (fb->pitches[0] !=
> >> -        drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
> >> -            drm_dbg_kms(&dev_priv->drm,
> >> -                        "Invalid cursor stride (%u) (cursor width %d)\n",
> >> -                        fb->pitches[0],
> >> -                        drm_rect_width(&plane_state->uapi.dst));
> >> -            return -EINVAL;
> >> -    }
> >> -
> >> -    /*
> >> -     * There's something wrong with the cursor on CHV pipe C.
> >> -     * If it straddles the left edge of the screen then
> >> -     * moving it away from the edge or disabling it often
> >> -     * results in a pipe underrun, and often that can lead to
> >> -     * dead pipe (constant underrun reported, and it scans
> >> -     * out just a solid color). To recover from that, the
> >> -     * display power well must be turned off and on again.
> >> -     * Refuse the put the cursor into that compromised position.
> >> -     */
> >> -    if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
> >> -        plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
> >> -            drm_dbg_kms(&dev_priv->drm,
> >> -                        "CHV cursor C not allowed to straddle the left screen edge\n");
> >> -            return -EINVAL;
> >> -    }
> >> -
> >> -    plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
> >> -
> >> -    return 0;
> >> -}
> >> -
> >> -static void i9xx_update_cursor(struct intel_plane *plane,
> >> -                           const struct intel_crtc_state *crtc_state,
> >> -                           const struct intel_plane_state *plane_state)
> >> -{
> >> -    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> -    enum pipe pipe = plane->pipe;
> >> -    u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
> >> -    unsigned long irqflags;
> >> -
> >> -    if (plane_state && plane_state->uapi.visible) {
> >> -            unsigned width = drm_rect_width(&plane_state->uapi.dst);
> >> -            unsigned height = drm_rect_height(&plane_state->uapi.dst);
> >> -
> >> -            cntl = plane_state->ctl |
> >> -                    i9xx_cursor_ctl_crtc(crtc_state);
> >> -
> >> -            if (width != height)
> >> -                    fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
> >> -
> >> -            base = intel_cursor_base(plane_state);
> >> -            pos = intel_cursor_position(plane_state);
> >> -    }
> >> -
> >> -    spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> >> -
> >> -    /*
> >> -     * On some platforms writing CURCNTR first will also
> >> -     * cause CURPOS to be armed by the CURBASE write.
> >> -     * Without the CURCNTR write the CURPOS write would
> >> -     * arm itself. Thus we always update CURCNTR before
> >> -     * CURPOS.
> >> -     *
> >> -     * On other platforms CURPOS always requires the
> >> -     * CURBASE write to arm the update. Additonally
> >> -     * a write to any of the cursor register will cancel
> >> -     * an already armed cursor update. Thus leaving out
> >> -     * the CURBASE write after CURPOS could lead to a
> >> -     * cursor that doesn't appear to move, or even change
> >> -     * shape. Thus we always write CURBASE.
> >> -     *
> >> -     * The other registers are armed by by the CURBASE write
> >> -     * except when the plane is getting enabled at which time
> >> -     * the CURCNTR write arms the update.
> >> -     */
> >> -
> >> -    if (INTEL_GEN(dev_priv) >= 9)
> >> -            skl_write_cursor_wm(plane, crtc_state);
> >> -
> >> -    if (!intel_crtc_needs_modeset(crtc_state))
> >> -            intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
> >> -
> >> -    if (plane->cursor.base != base ||
> >> -        plane->cursor.size != fbc_ctl ||
> >> -        plane->cursor.cntl != cntl) {
> >> -            if (HAS_CUR_FBC(dev_priv))
> >> -                    intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
> >> -                                      fbc_ctl);
> >> -            intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
> >> -            intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> >> -            intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> >> -
> >> -            plane->cursor.base = base;
> >> -            plane->cursor.size = fbc_ctl;
> >> -            plane->cursor.cntl = cntl;
> >> -    } else {
> >> -            intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
> >> -            intel_de_write_fw(dev_priv, CURBASE(pipe), base);
> >> -    }
> >> -
> >> -    spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> >> -}
> >> -
> >> -static void i9xx_disable_cursor(struct intel_plane *plane,
> >> -                            const struct intel_crtc_state *crtc_state)
> >> -{
> >> -    i9xx_update_cursor(plane, crtc_state, NULL);
> >> -}
> >> -
> >> -static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
> >> -                                 enum pipe *pipe)
> >> -{
> >> -    struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> -    enum intel_display_power_domain power_domain;
> >> -    intel_wakeref_t wakeref;
> >> -    bool ret;
> >> -    u32 val;
> >> -
> >> -    /*
> >> -     * Not 100% correct for planes that can move between pipes,
> >> -     * but that's only the case for gen2-3 which don't have any
> >> -     * display power wells.
> >> -     */
> >> -    power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> >> -    wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> >> -    if (!wakeref)
> >> -            return false;
> >> -
> >> -    val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
> >> -
> >> -    ret = val & MCURSOR_MODE;
> >> -
> >> -    if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> >> -            *pipe = plane->pipe;
> >> -    else
> >> -            *pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
> >> -                    MCURSOR_PIPE_SELECT_SHIFT;
> >> -
> >> -    intel_display_power_put(dev_priv, power_domain, wakeref);
> >> -
> >> -    return ret;
> >> -}
> >> -
> >>  /* VESA 640x480x72Hz mode to set on the pipe */
> >>  static const struct drm_display_mode load_detect_mode = {
> >>      DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
> >> @@ -16609,7 +16036,7 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc,
> >>      add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
> >>  }
> >>
> >> -static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
> >> +int intel_plane_pin_fb(struct intel_plane_state *plane_state)
> >>  {
> >>      struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> >>      struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >> @@ -16639,7 +16066,7 @@ static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
> >>      return 0;
> >>  }
> >>
> >> -static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
> >> +void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
> >>  {
> >>      struct i915_vma *vma;
> >>
> >> @@ -16875,13 +16302,6 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
> >>      }
> >>  }
> >>
> >> -static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
> >> -                                          u32 format, u64 modifier)
> >> -{
> >> -    return modifier == DRM_FORMAT_MOD_LINEAR &&
> >> -            format == DRM_FORMAT_ARGB8888;
> >> -}
> >> -
> >>  static const struct drm_plane_funcs i965_plane_funcs = {
> >>      .update_plane = drm_atomic_helper_update_plane,
> >>      .disable_plane = drm_atomic_helper_disable_plane,
> >> @@ -16900,142 +16320,6 @@ static const struct drm_plane_funcs i8xx_plane_funcs = {
> >>      .format_mod_supported = i8xx_plane_format_mod_supported,
> >>  };
> >>
> >> -static int
> >> -intel_legacy_cursor_update(struct drm_plane *_plane,
> >> -                       struct drm_crtc *_crtc,
> >> -                       struct drm_framebuffer *fb,
> >> -                       int crtc_x, int crtc_y,
> >> -                       unsigned int crtc_w, unsigned int crtc_h,
> >> -                       u32 src_x, u32 src_y,
> >> -                       u32 src_w, u32 src_h,
> >> -                       struct drm_modeset_acquire_ctx *ctx)
> >> -{
> >> -    struct intel_plane *plane = to_intel_plane(_plane);
> >> -    struct intel_crtc *crtc = to_intel_crtc(_crtc);
> >> -    struct intel_plane_state *old_plane_state =
> >> -            to_intel_plane_state(plane->base.state);
> >> -    struct intel_plane_state *new_plane_state;
> >> -    struct intel_crtc_state *crtc_state =
> >> -            to_intel_crtc_state(crtc->base.state);
> >> -    struct intel_crtc_state *new_crtc_state;
> >> -    int ret;
> >> -
> >> -    /*
> >> -     * When crtc is inactive or there is a modeset pending,
> >> -     * wait for it to complete in the slowpath
> >> -     *
> >> -     * FIXME bigjoiner fastpath would be good
> >> -     */
> >> -    if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
> >> -        crtc_state->update_pipe || crtc_state->bigjoiner)
> >> -            goto slow;
> >> -
> >> -    /*
> >> -     * Don't do an async update if there is an outstanding commit modifying
> >> -     * the plane.  This prevents our async update's changes from getting
> >> -     * overridden by a previous synchronous update's state.
> >> -     */
> >> -    if (old_plane_state->uapi.commit &&
> >> -        !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
> >> -            goto slow;
> >> -
> >> -    /*
> >> -     * If any parameters change that may affect watermarks,
> >> -     * take the slowpath. Only changing fb or position should be
> >> -     * in the fastpath.
> >> -     */
> >> -    if (old_plane_state->uapi.crtc != &crtc->base ||
> >> -        old_plane_state->uapi.src_w != src_w ||
> >> -        old_plane_state->uapi.src_h != src_h ||
> >> -        old_plane_state->uapi.crtc_w != crtc_w ||
> >> -        old_plane_state->uapi.crtc_h != crtc_h ||
> >> -        !old_plane_state->uapi.fb != !fb)
> >> -            goto slow;
> >> -
> >> -    new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
> >> -    if (!new_plane_state)
> >> -            return -ENOMEM;
> >> -
> >> -    new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
> >> -    if (!new_crtc_state) {
> >> -            ret = -ENOMEM;
> >> -            goto out_free;
> >> -    }
> >> -
> >> -    drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
> >> -
> >> -    new_plane_state->uapi.src_x = src_x;
> >> -    new_plane_state->uapi.src_y = src_y;
> >> -    new_plane_state->uapi.src_w = src_w;
> >> -    new_plane_state->uapi.src_h = src_h;
> >> -    new_plane_state->uapi.crtc_x = crtc_x;
> >> -    new_plane_state->uapi.crtc_y = crtc_y;
> >> -    new_plane_state->uapi.crtc_w = crtc_w;
> >> -    new_plane_state->uapi.crtc_h = crtc_h;
> >> -
> >> -    intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
> >> -
> >> -    ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
> >> -                                              old_plane_state, new_plane_state);
> >> -    if (ret)
> >> -            goto out_free;
> >> -
> >> -    ret = intel_plane_pin_fb(new_plane_state);
> >> -    if (ret)
> >> -            goto out_free;
> >> -
> >> -    intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
> >> -                            ORIGIN_FLIP);
> >> -    intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
> >> -                            to_intel_frontbuffer(new_plane_state->hw.fb),
> >> -                            plane->frontbuffer_bit);
> >> -
> >> -    /* Swap plane state */
> >> -    plane->base.state = &new_plane_state->uapi;
> >> -
> >> -    /*
> >> -     * We cannot swap crtc_state as it may be in use by an atomic commit or
> >> -     * page flip that's running simultaneously. If we swap crtc_state and
> >> -     * destroy the old state, we will cause a use-after-free there.
> >> -     *
> >> -     * Only update active_planes, which is needed for our internal
> >> -     * bookkeeping. Either value will do the right thing when updating
> >> -     * planes atomically. If the cursor was part of the atomic update then
> >> -     * we would have taken the slowpath.
> >> -     */
> >> -    crtc_state->active_planes = new_crtc_state->active_planes;
> >> -
> >> -    if (new_plane_state->uapi.visible)
> >> -            intel_update_plane(plane, crtc_state, new_plane_state);
> >> -    else
> >> -            intel_disable_plane(plane, crtc_state);
> >> -
> >> -    intel_plane_unpin_fb(old_plane_state);
> >> -
> >> -out_free:
> >> -    if (new_crtc_state)
> >> -            intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
> >> -    if (ret)
> >> -            intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
> >> -    else
> >> -            intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
> >> -    return ret;
> >> -
> >> -slow:
> >> -    return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
> >> -                                          crtc_x, crtc_y, crtc_w, crtc_h,
> >> -                                          src_x, src_y, src_w, src_h, ctx);
> >> -}
> >> -
> >> -static const struct drm_plane_funcs intel_cursor_plane_funcs = {
> >> -    .update_plane = intel_legacy_cursor_update,
> >> -    .disable_plane = drm_atomic_helper_disable_plane,
> >> -    .destroy = intel_plane_destroy,
> >> -    .atomic_duplicate_state = intel_plane_duplicate_state,
> >> -    .atomic_destroy_state = intel_plane_destroy_state,
> >> -    .format_mod_supported = intel_cursor_format_mod_supported,
> >> -};
> >> -
> >>  static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
> >>                             enum i9xx_plane_id i9xx_plane)
> >>  {
> >> @@ -17187,74 +16471,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> >>      return ERR_PTR(ret);
> >>  }
> >>
> >> -static struct intel_plane *
> >> -intel_cursor_plane_create(struct drm_i915_private *dev_priv,
> >> -                      enum pipe pipe)
> >> -{
> >> -    struct intel_plane *cursor;
> >> -    int ret, zpos;
> >> -
> >> -    cursor = intel_plane_alloc();
> >> -    if (IS_ERR(cursor))
> >> -            return cursor;
> >> -
> >> -    cursor->pipe = pipe;
> >> -    cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
> >> -    cursor->id = PLANE_CURSOR;
> >> -    cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
> >> -
> >> -    if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
> >> -            cursor->max_stride = i845_cursor_max_stride;
> >> -            cursor->update_plane = i845_update_cursor;
> >> -            cursor->disable_plane = i845_disable_cursor;
> >> -            cursor->get_hw_state = i845_cursor_get_hw_state;
> >> -            cursor->check_plane = i845_check_cursor;
> >> -    } else {
> >> -            cursor->max_stride = i9xx_cursor_max_stride;
> >> -            cursor->update_plane = i9xx_update_cursor;
> >> -            cursor->disable_plane = i9xx_disable_cursor;
> >> -            cursor->get_hw_state = i9xx_cursor_get_hw_state;
> >> -            cursor->check_plane = i9xx_check_cursor;
> >> -    }
> >> -
> >> -    cursor->cursor.base = ~0;
> >> -    cursor->cursor.cntl = ~0;
> >> -
> >> -    if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
> >> -            cursor->cursor.size = ~0;
> >> -
> >> -    ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
> >> -                                   0, &intel_cursor_plane_funcs,
> >> -                                   intel_cursor_formats,
> >> -                                   ARRAY_SIZE(intel_cursor_formats),
> >> -                                   cursor_format_modifiers,
> >> -                                   DRM_PLANE_TYPE_CURSOR,
> >> -                                   "cursor %c", pipe_name(pipe));
> >> -    if (ret)
> >> -            goto fail;
> >> -
> >> -    if (INTEL_GEN(dev_priv) >= 4)
> >> -            drm_plane_create_rotation_property(&cursor->base,
> >> -                                               DRM_MODE_ROTATE_0,
> >> -                                               DRM_MODE_ROTATE_0 |
> >> -                                               DRM_MODE_ROTATE_180);
> >> -
> >> -    zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
> >> -    drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
> >> -
> >> -    if (INTEL_GEN(dev_priv) >= 12)
> >> -            drm_plane_enable_fb_damage_clips(&cursor->base);
> >> -
> >> -    drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
> >> -
> >> -    return cursor;
> >> -
> >> -fail:
> >> -    intel_plane_free(cursor);
> >> -
> >> -    return ERR_PTR(ret);
> >> -}
> >> -
> >>  static int intel_crtc_late_register(struct drm_crtc *crtc)
> >>  {
> >>      intel_crtc_debugfs_add(crtc);
> >> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> >> index a5771bfecba6..f0a5bf69656f 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_display.h
> >> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> >> @@ -647,6 +647,18 @@ bool
> >>  intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
> >>                                  uint64_t modifier);
> >>
> >> +int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
> >> +u32 intel_plane_compute_aligned_offset(int *x, int *y,
> >> +                                   const struct intel_plane_state *state,
> >> +                                   int color_plane);
> >> +int intel_plane_pin_fb(struct intel_plane_state *plane_state);
> >> +void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
> >> +
> >> +/* cursor */
> >> +struct intel_plane *
> >> +intel_cursor_plane_create(struct drm_i915_private *dev_priv,
> >> +                      enum pipe pipe);
> >> +
> >>  /* modesetting */
> >>  void intel_modeset_init_hw(struct drm_i915_private *i915);
> >>  int intel_modeset_init_noirq(struct drm_i915_private *i915);
> >> --
> >> 2.27.0
> >>
> >> _______________________________________________
> >> Intel-gfx mailing list
> >> Intel-gfx@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Jani Nikula, Intel Open Source Graphics Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Intel-gfx] [PATCH 6/9] drm/i915: refactor pll code out into intel_dpll_legacy.c
  2020-12-10 15:18   ` Ville Syrjälä
@ 2020-12-10 16:31     ` Daniel Vetter
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Vetter @ 2020-12-10 16:31 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Thu, Dec 10, 2020 at 4:18 PM Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
>
> On Thu, Dec 10, 2020 at 02:17:52PM +1000, Dave Airlie wrote:
> > From: Dave Airlie <airlied@redhat.com>
> >
> > This pulls a large chunk of the pll calculation code out of
> > intel_display.c to a new file.
> >
> > One function makse sense to be an inline, otherwise this
> > is pretty much a straight copy cover. also all the
> > remaining hooks for g45 and older end up the same now.
> >
> > Signed-off-by: Dave Airlie <airlied@redhat.com>
> > ---
> >  drivers/gpu/drm/i915/Makefile                 |    1 +
> >  drivers/gpu/drm/i915/display/intel_display.c  | 1393 +----------------
> >  drivers/gpu/drm/i915/display/intel_display.h  |   13 +-
> >  .../drm/i915/display/intel_display_types.h    |    5 +
> >  .../gpu/drm/i915/display/intel_dpll_legacy.c  | 1370 ++++++++++++++++
> >  5 files changed, 1398 insertions(+), 1384 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/display/intel_dpll_legacy.c
> >
> <snip>
> > +static int hsw_crtc_compute_clock(struct intel_crtc *crtc,
> > +                               struct intel_crtc_state *crtc_state)
> > +{
> > +     struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +     struct intel_atomic_state *state =
> > +             to_intel_atomic_state(crtc_state->uapi.state);
> > +
> > +     if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
> > +         INTEL_GEN(dev_priv) >= 11) {
> > +             struct intel_encoder *encoder =
> > +                     intel_get_crtc_new_encoder(state, crtc_state);
> > +
> > +             if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
> > +                     drm_dbg_kms(&dev_priv->drm,
> > +                                 "failed to find PLL for pipe %c\n",
> > +                                 pipe_name(crtc->pipe));
> > +                     return -EINVAL;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
>
> If you're moving this then the "legacy" in the fine name is just
> wrong. I guess just call it intel_dpll.c if we lack a better idea?

Ah yes I missed that it's also pulling the ilk/hsw stuff which uses
the intel_dpll_mgr.c stuff. Probably more splitting to do eventually,
but just intel_dpll.c sounds reasonable for now.
-Daniel

>
> --
> Ville Syrjälä
> Intel
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2020-12-10 16:31 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-10  4:17 [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
2020-12-10  4:17 ` [Intel-gfx] [PATCH 1/9] drm/i915/display: move needs_modeset to an inline in header Dave Airlie
2020-12-10 15:08   ` Ville Syrjälä
2020-12-10  4:17 ` [Intel-gfx] [PATCH 2/9] drm/i915/display: move to_intel_frontbuffer to header Dave Airlie
2020-12-10 15:08   ` Ville Syrjälä
2020-12-10  4:17 ` [Intel-gfx] [PATCH 3/9] drm/i915/display: fix misused comma Dave Airlie
2020-12-10 15:09   ` Ville Syrjälä
2020-12-10  4:17 ` [Intel-gfx] [PATCH 4/9] drm/i915: refactor cursor code out of i915_display.c Dave Airlie
2020-12-10 15:06   ` Ville Syrjälä
2020-12-10 16:12     ` Jani Nikula
2020-12-10 16:17       ` Daniel Vetter
2020-12-10  4:17 ` [Intel-gfx] [PATCH 5/9] drm/i915: refactor some crtc code out of intel display Dave Airlie
2020-12-10 15:13   ` Ville Syrjälä
2020-12-10  4:17 ` [Intel-gfx] [PATCH 6/9] drm/i915: refactor pll code out into intel_dpll_legacy.c Dave Airlie
2020-12-10 15:18   ` Ville Syrjälä
2020-12-10 16:31     ` Daniel Vetter
2020-12-10  4:17 ` [Intel-gfx] [PATCH 7/9] drm/i915: split fdi code out from intel_display.c Dave Airlie
2020-12-10  4:17 ` [Intel-gfx] [PATCH 8/9] drm/i915: migrate hsw fdi code to new file Dave Airlie
2020-12-10  4:17 ` [Intel-gfx] [PATCH 9/9] drm/i915: migrate skl planes code " Dave Airlie
2020-12-10  4:32 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header Patchwork
2020-12-10  4:33 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2020-12-10  4:37 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
2020-12-10  5:02 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2020-12-10  7:11 ` [Intel-gfx] [RFC v2] refactor intel display a bit more Dave Airlie
2020-12-10  7:41 ` [Intel-gfx] ✓ Fi.CI.IGT: success for series starting with [1/9] drm/i915/display: move needs_modeset to an inline in header Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.