All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2)
@ 2016-12-19 17:28 ville.syrjala
  2016-12-19 17:28 ` [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state ville.syrjala
                   ` (14 more replies)
  0 siblings, 15 replies; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Attempt number two. This time it might actually work.

The main change involved actually committing the
correct thing, and comparing against the other correct
thing to know whether we need to commit it.

Full series:
git://github.com/vsyrjala/linux.git cdclk_state_3

Ville Syrjälä (14):
  drm/i915: Store the pipe pixel rate in the crtc state
  drm/i915: Nuke intel_mode_max_pixclk()
  drm/i915: s/get_display_clock_speed/get_cdclk/
  drm/i915: Clean up the .get_cdclk() assignment if ladder
  drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c
  drm/i915: Pass computed vco to bxt_set_cdclk()
  drm/i915: Start moving the cdclk stuff into a distinct state structure
  drm/i915: Track full cdclk state for the logical and actual cdclk
    frequencies
  drm/i915: Pass dev_priv to remainder of the cdclk functions
  drm/i915: Pass the cdclk state to the set_cdclk() functions
  drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk()
  drm/i915: Nuke the VLV/CHV PFI programming power domain workaround
  drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct
    .set_cdclk() hook
  drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c

 drivers/gpu/drm/i915/Makefile           |    1 +
 drivers/gpu/drm/i915/i915_debugfs.c     |    2 +-
 drivers/gpu/drm/i915/i915_drv.h         |   30 +-
 drivers/gpu/drm/i915/intel_audio.c      |    2 +-
 drivers/gpu/drm/i915/intel_cdclk.c      | 1767 ++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c    | 2218 ++++---------------------------
 drivers/gpu/drm/i915/intel_dp.c         |    4 +-
 drivers/gpu/drm/i915/intel_drv.h        |   41 +-
 drivers/gpu/drm/i915/intel_fbc.c        |    5 +-
 drivers/gpu/drm/i915/intel_panel.c      |    4 +-
 drivers/gpu/drm/i915/intel_pm.c         |   51 +-
 drivers/gpu/drm/i915/intel_runtime_pm.c |    6 +-
 12 files changed, 2117 insertions(+), 2014 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_cdclk.c

-- 
2.10.2

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

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

* [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-20 13:10   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk() ville.syrjala
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Rather than recomptuing the pipe pixel rate on demand everwhere, let's
just stick the precomputed value into the crtc state.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 31 ++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 drivers/gpu/drm/i915/intel_fbc.c     |  3 +--
 drivers/gpu/drm/i915/intel_pm.c      | 14 +++++++-------
 4 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0b0d7e8be630..1d979041c52c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7178,7 +7178,7 @@ static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
 	 *
 	 * Should measure whether using a lower cdclk w/o IPS
 	 */
-	return ilk_pipe_pixel_rate(pipe_config) <=
+	return pipe_config->pixel_rate <=
 		dev_priv->max_cdclk_freq * 95 / 100;
 }
 
@@ -7202,6 +7202,19 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
 		(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
 }
 
+static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+
+	if (HAS_GMCH_DISPLAY(dev_priv))
+		/* FIXME calculate proper pipe pixel rate GMCH pfit */
+		crtc_state->pixel_rate =
+			crtc_state->base.adjusted_mode.crtc_clock;
+	else
+		crtc_state->pixel_rate =
+			ilk_pipe_pixel_rate(crtc_state);
+}
+
 static int intel_crtc_compute_config(struct intel_crtc *crtc,
 				     struct intel_crtc_state *pipe_config)
 {
@@ -7248,6 +7261,8 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 		adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
 		return -EINVAL;
 
+	intel_crtc_compute_pixel_rate(pipe_config);
+
 	if (HAS_IPS(dev_priv))
 		hsw_compute_ips_config(crtc, pipe_config);
 
@@ -10297,7 +10312,7 @@ static int ilk_max_pixel_rate(struct drm_atomic_state *state)
 			continue;
 		}
 
-		pixel_rate = ilk_pipe_pixel_rate(crtc_state);
+		pixel_rate = crtc_state->pixel_rate;
 
 		if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
 			pixel_rate = bdw_adjust_min_pipe_pixel_rate(crtc_state,
@@ -12802,9 +12817,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 	DRM_DEBUG_KMS("adjusted mode:\n");
 	drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode);
 	intel_dump_crtc_timings(&pipe_config->base.adjusted_mode);
-	DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d\n",
+	DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d, pixel rate %d\n",
 		      pipe_config->port_clock,
-		      pipe_config->pipe_src_w, pipe_config->pipe_src_h);
+		      pipe_config->pipe_src_w, pipe_config->pipe_src_h,
+		      pipe_config->pixel_rate);
 
 	if (INTEL_GEN(dev_priv) >= 9)
 		DRM_DEBUG_KMS("num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n",
@@ -13409,6 +13425,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 		}
 
 		PIPE_CONF_CHECK_I(scaler_state.scaler_id);
+		PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate);
 	}
 
 	/* BDW+ don't expose a synchronous way to read the state */
@@ -13700,6 +13717,8 @@ verify_crtc_state(struct drm_crtc *crtc,
 		}
 	}
 
+	intel_crtc_compute_pixel_rate(pipe_config);
+
 	if (!new_crtc_state->active)
 		return;
 
@@ -16919,7 +16938,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 			dev_priv->active_crtcs |= 1 << crtc->pipe;
 
 			if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
-				pixclk = ilk_pipe_pixel_rate(crtc_state);
+				pixclk = crtc_state->pixel_rate;
 			else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 				pixclk = crtc_state->base.adjusted_mode.crtc_clock;
 			else
@@ -17031,6 +17050,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 			 */
 			crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
 
+			intel_crtc_compute_pixel_rate(crtc->config);
+
 			drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
 			update_scanline_offset(crtc);
 		}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f61ea43c7532..3969e786d566 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -541,6 +541,8 @@ struct intel_crtc_state {
 	 * and get clipped at the edges. */
 	int pipe_src_w, pipe_src_h;
 
+	unsigned int pixel_rate;
+
 	/* Whether to set up the PCH/FDI. Note that we never allow sharing
 	 * between pch encoders and cpu encoders. */
 	bool has_pch_encoder;
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 659cebc3bfd2..463056d80f9b 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -747,8 +747,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
 
 	cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-		cache->crtc.hsw_bdw_pixel_rate =
-			ilk_pipe_pixel_rate(crtc_state);
+		cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate;
 
 	cache->plane.rotation = plane_state->base.rotation;
 	cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7cbd6181a612..79e2be4216e4 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1807,12 +1807,12 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
 
 	cpp = pstate->base.fb->format->cpp[0];
 
-	method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value);
+	method1 = ilk_wm_method1(cstate->pixel_rate, cpp, mem_value);
 
 	if (!is_lp)
 		return method1;
 
-	method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
+	method2 = ilk_wm_method2(cstate->pixel_rate,
 				 cstate->base.adjusted_mode.crtc_htotal,
 				 drm_rect_width(&pstate->base.dst),
 				 cpp, mem_value);
@@ -1836,8 +1836,8 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
 
 	cpp = pstate->base.fb->format->cpp[0];
 
-	method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value);
-	method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
+	method1 = ilk_wm_method1(cstate->pixel_rate, cpp, mem_value);
+	method2 = ilk_wm_method2(cstate->pixel_rate,
 				 cstate->base.adjusted_mode.crtc_htotal,
 				 drm_rect_width(&pstate->base.dst),
 				 cpp, mem_value);
@@ -1863,7 +1863,7 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
 	if (!cstate->base.active)
 		return 0;
 
-	return ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
+	return ilk_wm_method2(cstate->pixel_rate,
 			      cstate->base.adjusted_mode.crtc_htotal,
 			      width, cpp, mem_value);
 }
@@ -3547,7 +3547,7 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst
 	 * Adjusted plane pixel rate is just the pipe's adjusted pixel rate
 	 * with additional adjustments for plane-specific scaling.
 	 */
-	adjusted_pixel_rate = ilk_pipe_pixel_rate(cstate);
+	adjusted_pixel_rate = cstate->pixel_rate;
 	downscale_amount = skl_plane_downscale_amount(pstate);
 
 	pixel_rate = adjusted_pixel_rate * downscale_amount >> 16;
@@ -3775,7 +3775,7 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate)
 	if (!cstate->base.active)
 		return 0;
 
-	pixel_rate = ilk_pipe_pixel_rate(cstate);
+	pixel_rate = cstate->pixel_rate;
 
 	if (WARN_ON(pixel_rate == 0))
 		return 0;
-- 
2.10.2

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

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

* [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk()
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
  2016-12-19 17:28 ` [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-20 13:22   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 03/14] drm/i915: s/get_display_clock_speed/get_cdclk/ ville.syrjala
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

ilk_max_pixel_rate() will now give the "correct" pixel rate for all
platforms, so let's kill rename it to intel_max_pixel_rate() and kill
off intel_mode_max_pixclk().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 41 ++++++------------------------------
 1 file changed, 6 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1d979041c52c..1e3f173a70e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -123,7 +123,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
 static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
-static int ilk_max_pixel_rate(struct drm_atomic_state *state);
+static int intel_max_pixel_rate(struct drm_atomic_state *state);
 static int glk_calc_cdclk(int max_pixclk);
 static int bxt_calc_cdclk(int max_pixclk);
 
@@ -6566,40 +6566,11 @@ static int bxt_calc_cdclk(int max_pixclk)
 		return 144000;
 }
 
-/* Compute the max pixel clock for new configuration. */
-static int intel_mode_max_pixclk(struct drm_device *dev,
-				 struct drm_atomic_state *state)
-{
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	unsigned max_pixclk = 0, i;
-	enum pipe pipe;
-
-	memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
-	       sizeof(intel_state->min_pixclk));
-
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		int pixclk = 0;
-
-		if (crtc_state->enable)
-			pixclk = crtc_state->adjusted_mode.crtc_clock;
-
-		intel_state->min_pixclk[i] = pixclk;
-	}
-
-	for_each_pipe(dev_priv, pipe)
-		max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
-
-	return max_pixclk;
-}
-
 static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int max_pixclk = intel_mode_max_pixclk(dev, state);
+	int max_pixclk = intel_max_pixel_rate(state);
 	struct intel_atomic_state *intel_state =
 		to_intel_atomic_state(state);
 
@@ -6615,7 +6586,7 @@ static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
 static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	int max_pixclk = ilk_max_pixel_rate(state);
+	int max_pixclk = intel_max_pixel_rate(state);
 	struct intel_atomic_state *intel_state =
 		to_intel_atomic_state(state);
 	int cdclk;
@@ -10290,7 +10261,7 @@ static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
 }
 
 /* compute the max rate for new configuration */
-static int ilk_max_pixel_rate(struct drm_atomic_state *state)
+static int intel_max_pixel_rate(struct drm_atomic_state *state)
 {
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
@@ -10422,7 +10393,7 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	int max_pixclk = ilk_max_pixel_rate(state);
+	int max_pixclk = intel_max_pixel_rate(state);
 	int cdclk;
 
 	/*
@@ -10458,7 +10429,7 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	const int max_pixclk = ilk_max_pixel_rate(state);
+	const int max_pixclk = intel_max_pixel_rate(state);
 	int vco = intel_state->cdclk_pll_vco;
 	int cdclk;
 
-- 
2.10.2

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

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

* [PATCH 03/14] drm/i915: s/get_display_clock_speed/get_cdclk/
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
  2016-12-19 17:28 ` [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state ville.syrjala
  2016-12-19 17:28 ` [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk() ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-20 13:27   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 04/14] drm/i915: Clean up the .get_cdclk() assignment if ladder ville.syrjala
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Rename the .get_display_clock_speed() hook to .get_cdclk().
.get_cdclk() is more specific (which clock) and it's much
shorter.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         |  2 +-
 drivers/gpu/drm/i915/intel_display.c    | 93 +++++++++++++--------------------
 drivers/gpu/drm/i915/intel_runtime_pm.c |  3 +-
 3 files changed, 39 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6217f01d3c11..393b34fb2d1a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -611,7 +611,7 @@ struct intel_limit;
 struct dpll;
 
 struct drm_i915_display_funcs {
-	int (*get_display_clock_speed)(struct drm_i915_private *dev_priv);
+	int (*get_cdclk)(struct drm_i915_private *dev_priv);
 	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
 	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
 	int (*compute_intermediate_wm)(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1e3f173a70e5..bbfef348783b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5873,7 +5873,7 @@ static void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
 
 static void intel_update_cdclk(struct drm_i915_private *dev_priv)
 {
-	dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev_priv);
+	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
 
 	if (INTEL_GEN(dev_priv) >= 9)
 		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
@@ -6411,8 +6411,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
-	WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
-					!= dev_priv->cdclk_freq);
+	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
 
 	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
 		cmd = 2;
@@ -6476,8 +6475,7 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
-	WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
-						!= dev_priv->cdclk_freq);
+	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
 
 	switch (cdclk) {
 	case 333333:
@@ -7243,7 +7241,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 	return 0;
 }
 
-static int skylake_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int skylake_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	u32 cdctl;
 
@@ -7304,7 +7302,7 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
 		dev_priv->cdclk_pll.ref;
 }
 
-static int broxton_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int broxton_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	u32 divider;
 	int div, vco;
@@ -7339,7 +7337,7 @@ static int broxton_get_display_clock_speed(struct drm_i915_private *dev_priv)
 	return DIV_ROUND_CLOSEST(vco, div);
 }
 
-static int broadwell_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int broadwell_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	uint32_t lcpll = I915_READ(LCPLL_CTL);
 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
@@ -7358,7 +7356,7 @@ static int broadwell_get_display_clock_speed(struct drm_i915_private *dev_priv)
 		return 675000;
 }
 
-static int haswell_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int haswell_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	uint32_t lcpll = I915_READ(LCPLL_CTL);
 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
@@ -7375,33 +7373,33 @@ static int haswell_get_display_clock_speed(struct drm_i915_private *dev_priv)
 		return 540000;
 }
 
-static int valleyview_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int valleyview_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
 				      CCK_DISPLAY_CLOCK_CONTROL);
 }
 
-static int ilk_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int ilk_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 450000;
 }
 
-static int i945_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i945_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 400000;
 }
 
-static int i915_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i915_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 333333;
 }
 
-static int i9xx_misc_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i9xx_misc_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 200000;
 }
 
-static int pnv_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 gcfgc = 0;
@@ -7426,7 +7424,7 @@ static int pnv_get_display_clock_speed(struct drm_i915_private *dev_priv)
 	}
 }
 
-static int i915gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 gcfgc = 0;
@@ -7446,12 +7444,12 @@ static int i915gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
 	}
 }
 
-static int i865_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i865_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 266667;
 }
 
-static int i85x_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 hpllcc = 0;
@@ -7489,7 +7487,7 @@ static int i85x_get_display_clock_speed(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
-static int i830_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i830_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 133333;
 }
@@ -7562,7 +7560,7 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
 	return vco;
 }
 
-static int gm45_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
@@ -7585,7 +7583,7 @@ static int gm45_get_display_clock_speed(struct drm_i915_private *dev_priv)
 	}
 }
 
-static int i965gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	static const uint8_t div_3200[] = { 16, 10,  8 };
@@ -7623,7 +7621,7 @@ static int i965gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
 	return 200000;
 }
 
-static int g33_get_display_clock_speed(struct drm_i915_private *dev_priv)
+static int g33_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
@@ -16091,58 +16089,41 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 
 	/* Returns the core display clock speed */
 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			skylake_get_display_clock_speed;
+		dev_priv->display.get_cdclk = skylake_get_cdclk;
 	else if (IS_GEN9_LP(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			broxton_get_display_clock_speed;
+		dev_priv->display.get_cdclk = broxton_get_cdclk;
 	else if (IS_BROADWELL(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			broadwell_get_display_clock_speed;
+		dev_priv->display.get_cdclk = broadwell_get_cdclk;
 	else if (IS_HASWELL(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			haswell_get_display_clock_speed;
+		dev_priv->display.get_cdclk = haswell_get_cdclk;
 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			valleyview_get_display_clock_speed;
+		dev_priv->display.get_cdclk = valleyview_get_cdclk;
 	else if (IS_GEN5(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			ilk_get_display_clock_speed;
+		dev_priv->display.get_cdclk = ilk_get_cdclk;
 	else if (IS_I945G(dev_priv) || IS_I965G(dev_priv) ||
 		 IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			i945_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i945_get_cdclk;
 	else if (IS_GM45(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			gm45_get_display_clock_speed;
+		dev_priv->display.get_cdclk = gm45_get_cdclk;
 	else if (IS_I965GM(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			i965gm_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i965gm_get_cdclk;
 	else if (IS_PINEVIEW(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			pnv_get_display_clock_speed;
+		dev_priv->display.get_cdclk = pnv_get_cdclk;
 	else if (IS_G33(dev_priv) || IS_G4X(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			g33_get_display_clock_speed;
+		dev_priv->display.get_cdclk = g33_get_cdclk;
 	else if (IS_I915G(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			i915_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i915_get_cdclk;
 	else if (IS_I945GM(dev_priv) || IS_I845G(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			i9xx_misc_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i9xx_misc_get_cdclk;
 	else if (IS_I915GM(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			i915gm_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i915gm_get_cdclk;
 	else if (IS_I865G(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			i865_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i865_get_cdclk;
 	else if (IS_I85X(dev_priv))
-		dev_priv->display.get_display_clock_speed =
-			i85x_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i85x_get_cdclk;
 	else { /* 830 */
 		WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz CDCLK\n");
-		dev_priv->display.get_display_clock_speed =
-			i830_get_display_clock_speed;
+		dev_priv->display.get_cdclk = i830_get_cdclk;
 	}
 
 	if (IS_GEN5(dev_priv)) {
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index c0b7e95b5b8e..6d5efeb35823 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -966,8 +966,7 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
 {
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
-	WARN_ON(dev_priv->cdclk_freq !=
-		dev_priv->display.get_display_clock_speed(dev_priv));
+	WARN_ON(dev_priv->cdclk_freq != dev_priv->display.get_cdclk(dev_priv));
 
 	gen9_assert_dbuf_enabled(dev_priv);
 
-- 
2.10.2

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

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

* [PATCH 04/14] drm/i915: Clean up the .get_cdclk() assignment if ladder
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (2 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH 03/14] drm/i915: s/get_display_clock_speed/get_cdclk/ ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-20 13:42   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c ville.syrjala
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Let's clean up the mess we have in the if ladder that assigns the
.get_cdclk() hooks. The grouping of the platforms by the function
results in a thing that's not really legible, so let's do it the
other way around and order the if ladder by platform and duplicate
whatever assignments we need.

To further avoid confusion with the function names let's rename
them to just fixed_<freq>_get_cdclk(). The other option would
be to duplicate the functions entirely but it seems quite
pointless to do that since each one just returns a fixed value.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 41 +++++++++++++++++++++---------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bbfef348783b..29f91e799272 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7379,22 +7379,22 @@ static int valleyview_get_cdclk(struct drm_i915_private *dev_priv)
 				      CCK_DISPLAY_CLOCK_CONTROL);
 }
 
-static int ilk_get_cdclk(struct drm_i915_private *dev_priv)
+static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 450000;
 }
 
-static int i945_get_cdclk(struct drm_i915_private *dev_priv)
+static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 400000;
 }
 
-static int i915_get_cdclk(struct drm_i915_private *dev_priv)
+static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 333333;
 }
 
-static int i9xx_misc_get_cdclk(struct drm_i915_private *dev_priv)
+static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 200000;
 }
@@ -7444,7 +7444,7 @@ static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
 	}
 }
 
-static int i865_get_cdclk(struct drm_i915_private *dev_priv)
+static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 266667;
 }
@@ -7487,7 +7487,7 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
-static int i830_get_cdclk(struct drm_i915_private *dev_priv)
+static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
 {
 	return 133333;
 }
@@ -16098,32 +16098,39 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 		dev_priv->display.get_cdclk = haswell_get_cdclk;
 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		dev_priv->display.get_cdclk = valleyview_get_cdclk;
+	else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
+		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
 	else if (IS_GEN5(dev_priv))
-		dev_priv->display.get_cdclk = ilk_get_cdclk;
-	else if (IS_I945G(dev_priv) || IS_I965G(dev_priv) ||
-		 IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
-		dev_priv->display.get_cdclk = i945_get_cdclk;
+		dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
 	else if (IS_GM45(dev_priv))
 		dev_priv->display.get_cdclk = gm45_get_cdclk;
+	else if (IS_G4X(dev_priv))
+		dev_priv->display.get_cdclk = g33_get_cdclk;
 	else if (IS_I965GM(dev_priv))
 		dev_priv->display.get_cdclk = i965gm_get_cdclk;
+	else if (IS_I965G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
 	else if (IS_PINEVIEW(dev_priv))
 		dev_priv->display.get_cdclk = pnv_get_cdclk;
-	else if (IS_G33(dev_priv) || IS_G4X(dev_priv))
+	else if (IS_G33(dev_priv))
 		dev_priv->display.get_cdclk = g33_get_cdclk;
-	else if (IS_I915G(dev_priv))
-		dev_priv->display.get_cdclk = i915_get_cdclk;
-	else if (IS_I945GM(dev_priv) || IS_I845G(dev_priv))
-		dev_priv->display.get_cdclk = i9xx_misc_get_cdclk;
+	else if (IS_I945GM(dev_priv))
+		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
+	else if (IS_I945G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
 	else if (IS_I915GM(dev_priv))
 		dev_priv->display.get_cdclk = i915gm_get_cdclk;
+	else if (IS_I915G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
 	else if (IS_I865G(dev_priv))
-		dev_priv->display.get_cdclk = i865_get_cdclk;
+		dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
 	else if (IS_I85X(dev_priv))
 		dev_priv->display.get_cdclk = i85x_get_cdclk;
+	else  if (IS_I845G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
 	else { /* 830 */
 		WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz CDCLK\n");
-		dev_priv->display.get_cdclk = i830_get_cdclk;
+		dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
 	}
 
 	if (IS_GEN5(dev_priv)) {
-- 
2.10.2

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

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

* [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (3 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH 04/14] drm/i915: Clean up the .get_cdclk() assignment if ladder ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-22 13:10   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 06/14] drm/i915: Pass computed vco to bxt_set_cdclk() ville.syrjala
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Let's try to shrink intel_display.c a bit by moving the cdclk/rawclk
stuff to a new file. It's all reasonably self contained so we don't
even have to add that many non-static symbols.

We'll also take the opportunity to shuffle around the functions a bit
to get things in a more consistent order based on the platform.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/Makefile        |    1 +
 drivers/gpu/drm/i915/intel_cdclk.c   | 1690 +++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c | 2115 ++++------------------------------
 drivers/gpu/drm/i915/intel_drv.h     |    9 +-
 4 files changed, 1922 insertions(+), 1893 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_cdclk.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5196509e71cf..3f5c21b76e85 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -70,6 +70,7 @@ i915-y += intel_audio.o \
 	  intel_atomic.o \
 	  intel_atomic_plane.o \
 	  intel_bios.o \
+	  intel_cdclk.o \
 	  intel_color.o \
 	  intel_display.o \
 	  intel_dpio_phy.o \
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
new file mode 100644
index 000000000000..1804c43553b7
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -0,0 +1,1690 @@
+/*
+ * Copyright © 2006-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "intel_drv.h"
+
+static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	return 133333;
+}
+
+static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	return 200000;
+}
+
+static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	return 266667;
+}
+
+static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	return 333333;
+}
+
+static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	return 400000;
+}
+
+static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	return 450000;
+}
+
+static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	u16 hpllcc = 0;
+
+	/*
+	 * 852GM/852GMV only supports 133 MHz and the HPLLCC
+	 * encoding is different :(
+	 * FIXME is this the right way to detect 852GM/852GMV?
+	 */
+	if (pdev->revision == 0x1)
+		return 133333;
+
+	pci_bus_read_config_word(pdev->bus,
+				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
+
+	/* Assume that the hardware is in the high speed state.  This
+	 * should be the default.
+	 */
+	switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
+	case GC_CLOCK_133_200:
+	case GC_CLOCK_133_200_2:
+	case GC_CLOCK_100_200:
+		return 200000;
+	case GC_CLOCK_166_250:
+		return 250000;
+	case GC_CLOCK_100_133:
+		return 133333;
+	case GC_CLOCK_133_266:
+	case GC_CLOCK_133_266_2:
+	case GC_CLOCK_166_266:
+		return 266667;
+	}
+
+	/* Shouldn't happen */
+	return 0;
+}
+
+static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	u16 gcfgc = 0;
+
+	pci_read_config_word(pdev, GCFGC, &gcfgc);
+
+	if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
+		return 133333;
+
+	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
+	case GC_DISPLAY_CLOCK_333_MHZ:
+		return 333333;
+	default:
+	case GC_DISPLAY_CLOCK_190_200_MHZ:
+		return 190000;
+	}
+}
+
+static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
+{
+	static const unsigned int blb_vco[8] = {
+		[0] = 3200000,
+		[1] = 4000000,
+		[2] = 5333333,
+		[3] = 4800000,
+		[4] = 6400000,
+	};
+	static const unsigned int pnv_vco[8] = {
+		[0] = 3200000,
+		[1] = 4000000,
+		[2] = 5333333,
+		[3] = 4800000,
+		[4] = 2666667,
+	};
+	static const unsigned int cl_vco[8] = {
+		[0] = 3200000,
+		[1] = 4000000,
+		[2] = 5333333,
+		[3] = 6400000,
+		[4] = 3333333,
+		[5] = 3566667,
+		[6] = 4266667,
+	};
+	static const unsigned int elk_vco[8] = {
+		[0] = 3200000,
+		[1] = 4000000,
+		[2] = 5333333,
+		[3] = 4800000,
+	};
+	static const unsigned int ctg_vco[8] = {
+		[0] = 3200000,
+		[1] = 4000000,
+		[2] = 5333333,
+		[3] = 6400000,
+		[4] = 2666667,
+		[5] = 4266667,
+	};
+	const unsigned int *vco_table;
+	unsigned int vco;
+	uint8_t tmp = 0;
+
+	/* FIXME other chipsets? */
+	if (IS_GM45(dev_priv))
+		vco_table = ctg_vco;
+	else if (IS_G4X(dev_priv))
+		vco_table = elk_vco;
+	else if (IS_I965GM(dev_priv))
+		vco_table = cl_vco;
+	else if (IS_PINEVIEW(dev_priv))
+		vco_table = pnv_vco;
+	else if (IS_G33(dev_priv))
+		vco_table = blb_vco;
+	else
+		return 0;
+
+	tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
+
+	vco = vco_table[tmp & 0x7];
+	if (vco == 0)
+		DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
+	else
+		DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
+
+	return vco;
+}
+
+static int g33_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
+	static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
+	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
+	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
+	const uint8_t *div_table;
+	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+	uint16_t tmp = 0;
+
+	pci_read_config_word(pdev, GCFGC, &tmp);
+
+	cdclk_sel = (tmp >> 4) & 0x7;
+
+	if (cdclk_sel >= ARRAY_SIZE(div_3200))
+		goto fail;
+
+	switch (vco) {
+	case 3200000:
+		div_table = div_3200;
+		break;
+	case 4000000:
+		div_table = div_4000;
+		break;
+	case 4800000:
+		div_table = div_4800;
+		break;
+	case 5333333:
+		div_table = div_5333;
+		break;
+	default:
+		goto fail;
+	}
+
+	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
+
+fail:
+	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
+		  vco, tmp);
+	return 190476;
+}
+
+static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	u16 gcfgc = 0;
+
+	pci_read_config_word(pdev, GCFGC, &gcfgc);
+
+	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
+	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
+		return 266667;
+	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
+		return 333333;
+	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
+		return 444444;
+	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
+		return 200000;
+	default:
+		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
+	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
+		return 133333;
+	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
+		return 166667;
+	}
+}
+
+static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	static const uint8_t div_3200[] = { 16, 10,  8 };
+	static const uint8_t div_4000[] = { 20, 12, 10 };
+	static const uint8_t div_5333[] = { 24, 16, 14 };
+	const uint8_t *div_table;
+	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+	uint16_t tmp = 0;
+
+	pci_read_config_word(pdev, GCFGC, &tmp);
+
+	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
+
+	if (cdclk_sel >= ARRAY_SIZE(div_3200))
+		goto fail;
+
+	switch (vco) {
+	case 3200000:
+		div_table = div_3200;
+		break;
+	case 4000000:
+		div_table = div_4000;
+		break;
+	case 5333333:
+		div_table = div_5333;
+		break;
+	default:
+		goto fail;
+	}
+
+	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
+
+fail:
+	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
+		  vco, tmp);
+	return 200000;
+}
+
+static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+	uint16_t tmp = 0;
+
+	pci_read_config_word(pdev, GCFGC, &tmp);
+
+	cdclk_sel = (tmp >> 12) & 0x1;
+
+	switch (vco) {
+	case 2666667:
+	case 4000000:
+	case 5333333:
+		return cdclk_sel ? 333333 : 222222;
+	case 3200000:
+		return cdclk_sel ? 320000 : 228571;
+	default:
+		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
+			  vco, tmp);
+		return 222222;
+	}
+}
+
+static int hsw_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	uint32_t lcpll = I915_READ(LCPLL_CTL);
+	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
+
+	if (lcpll & LCPLL_CD_SOURCE_FCLK)
+		return 800000;
+	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
+		return 450000;
+	else if (freq == LCPLL_CLK_FREQ_450)
+		return 450000;
+	else if (IS_HSW_ULT(dev_priv))
+		return 337500;
+	else
+		return 540000;
+}
+
+static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
+			  int max_pixclk)
+{
+	int freq_320 = (dev_priv->hpll_freq <<  1) % 320000 != 0 ?
+		333333 : 320000;
+	int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
+
+	/*
+	 * We seem to get an unstable or solid color picture at 200MHz.
+	 * Not sure what's wrong. For now use 200MHz only when all pipes
+	 * are off.
+	 */
+	if (!IS_CHERRYVIEW(dev_priv) &&
+	    max_pixclk > freq_320*limit/100)
+		return 400000;
+	else if (max_pixclk > 266667*limit/100)
+		return freq_320;
+	else if (max_pixclk > 0)
+		return 266667;
+	else
+		return 200000;
+}
+
+static int vlv_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
+				      CCK_DISPLAY_CLOCK_CONTROL);
+}
+
+static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
+{
+	unsigned int credits, default_credits;
+
+	if (IS_CHERRYVIEW(dev_priv))
+		default_credits = PFI_CREDIT(12);
+	else
+		default_credits = PFI_CREDIT(8);
+
+	if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
+		/* CHV suggested value is 31 or 63 */
+		if (IS_CHERRYVIEW(dev_priv))
+			credits = PFI_CREDIT_63;
+		else
+			credits = PFI_CREDIT(15);
+	} else {
+		credits = default_credits;
+	}
+
+	/*
+	 * WA - write default credits before re-programming
+	 * FIXME: should we also set the resend bit here?
+	 */
+	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
+		   default_credits);
+
+	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
+		   credits | PFI_CREDIT_RESEND);
+
+	/*
+	 * FIXME is this guaranteed to clear
+	 * immediately or should we poll for it?
+	 */
+	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
+}
+
+static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	u32 val, cmd;
+
+	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
+
+	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
+		cmd = 2;
+	else if (cdclk == 266667)
+		cmd = 1;
+	else
+		cmd = 0;
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
+	val &= ~DSPFREQGUAR_MASK;
+	val |= (cmd << DSPFREQGUAR_SHIFT);
+	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
+	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
+		      DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
+		     50)) {
+		DRM_ERROR("timed out waiting for CDclk change\n");
+	}
+	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	if (cdclk == 400000) {
+		u32 divider;
+
+		divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1,
+					    cdclk) - 1;
+
+		/* adjust cdclk divider */
+		val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+		val &= ~CCK_FREQUENCY_VALUES;
+		val |= divider;
+		vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
+
+		if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
+			      CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
+			     50))
+			DRM_ERROR("timed out waiting for CDclk change\n");
+	}
+
+	/* adjust self-refresh exit latency value */
+	val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
+	val &= ~0x7f;
+
+	/*
+	 * For high bandwidth configs, we set a higher latency in the bunit
+	 * so that the core display fetch happens in time to avoid underruns.
+	 */
+	if (cdclk == 400000)
+		val |= 4500 / 250; /* 4.5 usec */
+	else
+		val |= 3000 / 250; /* 3.0 usec */
+	vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
+
+	mutex_unlock(&dev_priv->sb_lock);
+
+	intel_update_cdclk(dev_priv);
+}
+
+static void chv_set_cdclk(struct drm_device *dev, int cdclk)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	u32 val, cmd;
+
+	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
+
+	switch (cdclk) {
+	case 333333:
+	case 320000:
+	case 266667:
+	case 200000:
+		break;
+	default:
+		MISSING_CASE(cdclk);
+		return;
+	}
+
+	/*
+	 * Specs are full of misinformation, but testing on actual
+	 * hardware has shown that we just need to write the desired
+	 * CCK divider into the Punit register.
+	 */
+	cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
+	val &= ~DSPFREQGUAR_MASK_CHV;
+	val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
+	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
+	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
+		      DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
+		     50)) {
+		DRM_ERROR("timed out waiting for CDclk change\n");
+	}
+	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	intel_update_cdclk(dev_priv);
+}
+
+static int bdw_calc_cdclk(int max_pixclk)
+{
+	if (max_pixclk > 540000)
+		return 675000;
+	else if (max_pixclk > 450000)
+		return 540000;
+	else if (max_pixclk > 337500)
+		return 450000;
+	else
+		return 337500;
+}
+
+static int bdw_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	uint32_t lcpll = I915_READ(LCPLL_CTL);
+	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
+
+	if (lcpll & LCPLL_CD_SOURCE_FCLK)
+		return 800000;
+	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
+		return 450000;
+	else if (freq == LCPLL_CLK_FREQ_450)
+		return 450000;
+	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
+		return 540000;
+	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
+		return 337500;
+	else
+		return 675000;
+}
+
+static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	uint32_t val, data;
+	int ret;
+
+	if (WARN((I915_READ(LCPLL_CTL) &
+		  (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
+		   LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
+		   LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
+		   LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
+		 "trying to change cdclk frequency with cdclk not enabled\n"))
+		return;
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	ret = sandybridge_pcode_write(dev_priv,
+				      BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+	if (ret) {
+		DRM_ERROR("failed to inform pcode about cdclk change\n");
+		return;
+	}
+
+	val = I915_READ(LCPLL_CTL);
+	val |= LCPLL_CD_SOURCE_FCLK;
+	I915_WRITE(LCPLL_CTL, val);
+
+	if (wait_for_us(I915_READ(LCPLL_CTL) &
+			LCPLL_CD_SOURCE_FCLK_DONE, 1))
+		DRM_ERROR("Switching to FCLK failed\n");
+
+	val = I915_READ(LCPLL_CTL);
+	val &= ~LCPLL_CLK_FREQ_MASK;
+
+	switch (cdclk) {
+	case 450000:
+		val |= LCPLL_CLK_FREQ_450;
+		data = 0;
+		break;
+	case 540000:
+		val |= LCPLL_CLK_FREQ_54O_BDW;
+		data = 1;
+		break;
+	case 337500:
+		val |= LCPLL_CLK_FREQ_337_5_BDW;
+		data = 2;
+		break;
+	case 675000:
+		val |= LCPLL_CLK_FREQ_675_BDW;
+		data = 3;
+		break;
+	default:
+		WARN(1, "invalid cdclk frequency\n");
+		return;
+	}
+
+	I915_WRITE(LCPLL_CTL, val);
+
+	val = I915_READ(LCPLL_CTL);
+	val &= ~LCPLL_CD_SOURCE_FCLK;
+	I915_WRITE(LCPLL_CTL, val);
+
+	if (wait_for_us((I915_READ(LCPLL_CTL) &
+			LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
+		DRM_ERROR("Switching back to LCPLL failed\n");
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
+
+	intel_update_cdclk(dev_priv);
+
+	WARN(cdclk != dev_priv->cdclk_freq,
+	     "cdclk requested %d kHz but got %d kHz\n",
+	     cdclk, dev_priv->cdclk_freq);
+}
+
+static int skl_calc_cdclk(int max_pixclk, int vco)
+{
+	if (vco == 8640000) {
+		if (max_pixclk > 540000)
+			return 617143;
+		else if (max_pixclk > 432000)
+			return 540000;
+		else if (max_pixclk > 308571)
+			return 432000;
+		else
+			return 308571;
+	} else {
+		if (max_pixclk > 540000)
+			return 675000;
+		else if (max_pixclk > 450000)
+			return 540000;
+		else if (max_pixclk > 337500)
+			return 450000;
+		else
+			return 337500;
+	}
+}
+
+static void skl_dpll0_update(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+
+	dev_priv->cdclk_pll.ref = 24000;
+	dev_priv->cdclk_pll.vco = 0;
+
+	val = I915_READ(LCPLL1_CTL);
+	if ((val & LCPLL_PLL_ENABLE) == 0)
+		return;
+
+	if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
+		return;
+
+	val = I915_READ(DPLL_CTRL1);
+
+	if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
+			    DPLL_CTRL1_SSC(SKL_DPLL0) |
+			    DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
+		    DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
+		return;
+
+	switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
+	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
+	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
+	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
+	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
+		dev_priv->cdclk_pll.vco = 8100000;
+		break;
+	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
+	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
+		dev_priv->cdclk_pll.vco = 8640000;
+		break;
+	default:
+		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
+		break;
+	}
+}
+
+static int skl_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	u32 cdctl;
+
+	skl_dpll0_update(dev_priv);
+
+	if (dev_priv->cdclk_pll.vco == 0)
+		return dev_priv->cdclk_pll.ref;
+
+	cdctl = I915_READ(CDCLK_CTL);
+
+	if (dev_priv->cdclk_pll.vco == 8640000) {
+		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
+		case CDCLK_FREQ_450_432:
+			return 432000;
+		case CDCLK_FREQ_337_308:
+			return 308571;
+		case CDCLK_FREQ_540:
+			return 540000;
+		case CDCLK_FREQ_675_617:
+			return 617143;
+		default:
+			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
+		}
+	} else {
+		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
+		case CDCLK_FREQ_450_432:
+			return 450000;
+		case CDCLK_FREQ_337_308:
+			return 337500;
+		case CDCLK_FREQ_540:
+			return 540000;
+		case CDCLK_FREQ_675_617:
+			return 675000;
+		default:
+			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
+		}
+	}
+
+	return dev_priv->cdclk_pll.ref;
+}
+
+/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
+static int skl_cdclk_decimal(int cdclk)
+{
+	return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
+}
+
+static void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv,
+					int vco)
+{
+	bool changed = dev_priv->skl_preferred_vco_freq != vco;
+
+	dev_priv->skl_preferred_vco_freq = vco;
+
+	if (changed)
+		intel_update_max_cdclk(dev_priv);
+}
+
+static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
+{
+	int min_cdclk = skl_calc_cdclk(0, vco);
+	u32 val;
+
+	WARN_ON(vco != 8100000 && vco != 8640000);
+
+	/* select the minimum CDCLK before enabling DPLL 0 */
+	val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
+	I915_WRITE(CDCLK_CTL, val);
+	POSTING_READ(CDCLK_CTL);
+
+	/*
+	 * We always enable DPLL0 with the lowest link rate possible, but still
+	 * taking into account the VCO required to operate the eDP panel at the
+	 * desired frequency. The usual DP link rates operate with a VCO of
+	 * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
+	 * The modeset code is responsible for the selection of the exact link
+	 * rate later on, with the constraint of choosing a frequency that
+	 * works with vco.
+	 */
+	val = I915_READ(DPLL_CTRL1);
+
+	val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0) |
+		 DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
+	val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
+	if (vco == 8640000)
+		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
+					    SKL_DPLL0);
+	else
+		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
+					    SKL_DPLL0);
+
+	I915_WRITE(DPLL_CTRL1, val);
+	POSTING_READ(DPLL_CTRL1);
+
+	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
+
+	if (intel_wait_for_register(dev_priv,
+				    LCPLL1_CTL, LCPLL_PLL_LOCK, LCPLL_PLL_LOCK,
+				    5))
+		DRM_ERROR("DPLL0 not locked\n");
+
+	dev_priv->cdclk_pll.vco = vco;
+
+	/* We'll want to keep using the current vco from now on. */
+	skl_set_preferred_cdclk_vco(dev_priv, vco);
+}
+
+static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
+	if (intel_wait_for_register(dev_priv,
+				   LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
+				   1))
+		DRM_ERROR("Couldn't disable DPLL0\n");
+
+	dev_priv->cdclk_pll.vco = 0;
+}
+
+static void skl_set_cdclk(struct drm_i915_private *dev_priv,
+			  int cdclk, int vco)
+{
+	u32 freq_select, pcu_ack;
+	int ret;
+
+	WARN_ON((cdclk == 24000) != (vco == 0));
+
+	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
+			 cdclk, vco);
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
+				SKL_CDCLK_PREPARE_FOR_CHANGE,
+				SKL_CDCLK_READY_FOR_CHANGE,
+				SKL_CDCLK_READY_FOR_CHANGE, 3);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+	if (ret) {
+		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
+			  ret);
+		return;
+	}
+
+	/* set CDCLK_CTL */
+	switch (cdclk) {
+	case 450000:
+	case 432000:
+		freq_select = CDCLK_FREQ_450_432;
+		pcu_ack = 1;
+		break;
+	case 540000:
+		freq_select = CDCLK_FREQ_540;
+		pcu_ack = 2;
+		break;
+	case 308571:
+	case 337500:
+	default:
+		freq_select = CDCLK_FREQ_337_308;
+		pcu_ack = 0;
+		break;
+	case 617143:
+	case 675000:
+		freq_select = CDCLK_FREQ_675_617;
+		pcu_ack = 3;
+		break;
+	}
+
+	if (dev_priv->cdclk_pll.vco != 0 &&
+	    dev_priv->cdclk_pll.vco != vco)
+		skl_dpll0_disable(dev_priv);
+
+	if (dev_priv->cdclk_pll.vco != vco)
+		skl_dpll0_enable(dev_priv, vco);
+
+	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
+	POSTING_READ(CDCLK_CTL);
+
+	/* inform PCU of the change */
+	mutex_lock(&dev_priv->rps.hw_lock);
+	sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	intel_update_cdclk(dev_priv);
+}
+
+static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
+{
+	uint32_t cdctl, expected;
+
+	/*
+	 * check if the pre-os initialized the display
+	 * There is SWF18 scratchpad register defined which is set by the
+	 * pre-os which can be used by the OS drivers to check the status
+	 */
+	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
+		goto sanitize;
+
+	intel_update_cdclk(dev_priv);
+	/* Is PLL enabled and locked ? */
+	if (dev_priv->cdclk_pll.vco == 0 ||
+	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
+		goto sanitize;
+
+	/* DPLL okay; verify the cdclock
+	 *
+	 * Noticed in some instances that the freq selection is correct but
+	 * decimal part is programmed wrong from BIOS where pre-os does not
+	 * enable display. Verify the same as well.
+	 */
+	cdctl = I915_READ(CDCLK_CTL);
+	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
+		skl_cdclk_decimal(dev_priv->cdclk_freq);
+	if (cdctl == expected)
+		/* All well; nothing to sanitize */
+		return;
+
+sanitize:
+	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
+
+	/* force cdclk programming */
+	dev_priv->cdclk_freq = 0;
+	/* force full PLL disable + enable */
+	dev_priv->cdclk_pll.vco = -1;
+}
+
+void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
+{
+	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
+}
+
+void skl_init_cdclk(struct drm_i915_private *dev_priv)
+{
+	int cdclk, vco;
+
+	skl_sanitize_cdclk(dev_priv);
+
+	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
+		/*
+		 * Use the current vco as our initial
+		 * guess as to what the preferred vco is.
+		 */
+		if (dev_priv->skl_preferred_vco_freq == 0)
+			skl_set_preferred_cdclk_vco(dev_priv,
+						    dev_priv->cdclk_pll.vco);
+		return;
+	}
+
+	vco = dev_priv->skl_preferred_vco_freq;
+	if (vco == 0)
+		vco = 8100000;
+	cdclk = skl_calc_cdclk(0, vco);
+
+	skl_set_cdclk(dev_priv, cdclk, vco);
+}
+
+static int bxt_calc_cdclk(int max_pixclk)
+{
+	if (max_pixclk > 576000)
+		return 624000;
+	else if (max_pixclk > 384000)
+		return 576000;
+	else if (max_pixclk > 288000)
+		return 384000;
+	else if (max_pixclk > 144000)
+		return 288000;
+	else
+		return 144000;
+}
+
+static int glk_calc_cdclk(int max_pixclk)
+{
+	if (max_pixclk > 2 * 158400)
+		return 316800;
+	else if (max_pixclk > 2 * 79200)
+		return 158400;
+	else
+		return 79200;
+}
+
+static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
+{
+	int ratio;
+
+	if (cdclk == dev_priv->cdclk_pll.ref)
+		return 0;
+
+	switch (cdclk) {
+	default:
+		MISSING_CASE(cdclk);
+	case 144000:
+	case 288000:
+	case 384000:
+	case 576000:
+		ratio = 60;
+		break;
+	case 624000:
+		ratio = 65;
+		break;
+	}
+
+	return dev_priv->cdclk_pll.ref * ratio;
+}
+
+static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
+{
+	int ratio;
+
+	if (cdclk == dev_priv->cdclk_pll.ref)
+		return 0;
+
+	switch (cdclk) {
+	default:
+		MISSING_CASE(cdclk);
+	case  79200:
+	case 158400:
+	case 316800:
+		ratio = 33;
+		break;
+	}
+
+	return dev_priv->cdclk_pll.ref * ratio;
+}
+
+static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+
+	dev_priv->cdclk_pll.ref = 19200;
+	dev_priv->cdclk_pll.vco = 0;
+
+	val = I915_READ(BXT_DE_PLL_ENABLE);
+	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
+		return;
+
+	if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
+		return;
+
+	val = I915_READ(BXT_DE_PLL_CTL);
+	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
+		dev_priv->cdclk_pll.ref;
+}
+
+static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
+{
+	u32 divider;
+	int div, vco;
+
+	bxt_de_pll_update(dev_priv);
+
+	vco = dev_priv->cdclk_pll.vco;
+	if (vco == 0)
+		return dev_priv->cdclk_pll.ref;
+
+	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
+
+	switch (divider) {
+	case BXT_CDCLK_CD2X_DIV_SEL_1:
+		div = 2;
+		break;
+	case BXT_CDCLK_CD2X_DIV_SEL_1_5:
+		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
+		div = 3;
+		break;
+	case BXT_CDCLK_CD2X_DIV_SEL_2:
+		div = 4;
+		break;
+	case BXT_CDCLK_CD2X_DIV_SEL_4:
+		div = 8;
+		break;
+	default:
+		MISSING_CASE(divider);
+		return dev_priv->cdclk_pll.ref;
+	}
+
+	return DIV_ROUND_CLOSEST(vco, div);
+}
+
+static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE(BXT_DE_PLL_ENABLE, 0);
+
+	/* Timeout 200us */
+	if (intel_wait_for_register(dev_priv,
+				    BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
+				    1))
+		DRM_ERROR("timeout waiting for DE PLL unlock\n");
+
+	dev_priv->cdclk_pll.vco = 0;
+}
+
+static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
+{
+	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
+	u32 val;
+
+	val = I915_READ(BXT_DE_PLL_CTL);
+	val &= ~BXT_DE_PLL_RATIO_MASK;
+	val |= BXT_DE_PLL_RATIO(ratio);
+	I915_WRITE(BXT_DE_PLL_CTL, val);
+
+	I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
+
+	/* Timeout 200us */
+	if (intel_wait_for_register(dev_priv,
+				    BXT_DE_PLL_ENABLE,
+				    BXT_DE_PLL_LOCK,
+				    BXT_DE_PLL_LOCK,
+				    1))
+		DRM_ERROR("timeout waiting for DE PLL lock\n");
+
+	dev_priv->cdclk_pll.vco = vco;
+}
+
+static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+{
+	u32 val, divider;
+	int vco, ret;
+
+	if (IS_GEMINILAKE(dev_priv))
+		vco = glk_de_pll_vco(dev_priv, cdclk);
+	else
+		vco = bxt_de_pll_vco(dev_priv, cdclk);
+
+	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
+			 cdclk, vco);
+
+	/* cdclk = vco / 2 / div{1,1.5,2,4} */
+	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
+	case 8:
+		divider = BXT_CDCLK_CD2X_DIV_SEL_4;
+		break;
+	case 4:
+		divider = BXT_CDCLK_CD2X_DIV_SEL_2;
+		break;
+	case 3:
+		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
+		divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
+		break;
+	case 2:
+		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
+		break;
+	default:
+		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
+		WARN_ON(vco != 0);
+
+		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
+		break;
+	}
+
+	/* Inform power controller of upcoming frequency change */
+	mutex_lock(&dev_priv->rps.hw_lock);
+	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
+				      0x80000000);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	if (ret) {
+		DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n",
+			  ret, cdclk);
+		return;
+	}
+
+	if (dev_priv->cdclk_pll.vco != 0 &&
+	    dev_priv->cdclk_pll.vco != vco)
+		bxt_de_pll_disable(dev_priv);
+
+	if (dev_priv->cdclk_pll.vco != vco)
+		bxt_de_pll_enable(dev_priv, vco);
+
+	val = divider | skl_cdclk_decimal(cdclk);
+	/*
+	 * FIXME if only the cd2x divider needs changing, it could be done
+	 * without shutting off the pipe (if only one pipe is active).
+	 */
+	val |= BXT_CDCLK_CD2X_PIPE_NONE;
+	/*
+	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
+	 * enable otherwise.
+	 */
+	if (cdclk >= 500000)
+		val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
+	I915_WRITE(CDCLK_CTL, val);
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
+				      DIV_ROUND_UP(cdclk, 25000));
+	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	if (ret) {
+		DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
+			  ret, cdclk);
+		return;
+	}
+
+	intel_update_cdclk(dev_priv);
+}
+
+static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
+{
+	u32 cdctl, expected;
+
+	intel_update_cdclk(dev_priv);
+
+	if (dev_priv->cdclk_pll.vco == 0 ||
+	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
+		goto sanitize;
+
+	/* DPLL okay; verify the cdclock
+	 *
+	 * Some BIOS versions leave an incorrect decimal frequency value and
+	 * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
+	 * so sanitize this register.
+	 */
+	cdctl = I915_READ(CDCLK_CTL);
+	/*
+	 * Let's ignore the pipe field, since BIOS could have configured the
+	 * dividers both synching to an active pipe, or asynchronously
+	 * (PIPE_NONE).
+	 */
+	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
+
+	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
+		   skl_cdclk_decimal(dev_priv->cdclk_freq);
+	/*
+	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
+	 * enable otherwise.
+	 */
+	if (dev_priv->cdclk_freq >= 500000)
+		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
+
+	if (cdctl == expected)
+		/* All well; nothing to sanitize */
+		return;
+
+sanitize:
+	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
+
+	/* force cdclk programming */
+	dev_priv->cdclk_freq = 0;
+
+	/* force full PLL disable + enable */
+	dev_priv->cdclk_pll.vco = -1;
+}
+
+void bxt_init_cdclk(struct drm_i915_private *dev_priv)
+{
+	int cdclk;
+
+	bxt_sanitize_cdclk(dev_priv);
+
+	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
+		return;
+
+	/*
+	 * FIXME:
+	 * - The initial CDCLK needs to be read from VBT.
+	 *   Need to make this change after VBT has changes for BXT.
+	 */
+	if (IS_GEMINILAKE(dev_priv))
+		cdclk = glk_calc_cdclk(0);
+	else
+		cdclk = bxt_calc_cdclk(0);
+
+	bxt_set_cdclk(dev_priv, cdclk);
+}
+
+void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
+{
+	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
+}
+
+static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
+					  int pixel_rate)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(crtc_state->base.crtc->dev);
+
+	/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
+	if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
+		pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
+
+	/* BSpec says "Do not use DisplayPort with CDCLK less than
+	 * 432 MHz, audio enabled, port width x4, and link rate
+	 * HBR2 (5.4 GHz), or else there may be audio corruption or
+	 * screen corruption."
+	 */
+	if (intel_crtc_has_dp_encoder(crtc_state) &&
+	    crtc_state->has_audio &&
+	    crtc_state->port_clock >= 540000 &&
+	    crtc_state->lane_count == 4)
+		pixel_rate = max(432000, pixel_rate);
+
+	return pixel_rate;
+}
+
+/* compute the max rate for new configuration */
+static int intel_max_pixel_rate(struct drm_atomic_state *state)
+{
+	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+	struct drm_i915_private *dev_priv = to_i915(state->dev);
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *cstate;
+	struct intel_crtc_state *crtc_state;
+	unsigned int max_pixel_rate = 0, i;
+	enum pipe pipe;
+
+	memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
+	       sizeof(intel_state->min_pixclk));
+
+	for_each_crtc_in_state(state, crtc, cstate, i) {
+		int pixel_rate;
+
+		crtc_state = to_intel_crtc_state(cstate);
+		if (!crtc_state->base.enable) {
+			intel_state->min_pixclk[i] = 0;
+			continue;
+		}
+
+		pixel_rate = crtc_state->pixel_rate;
+
+		if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
+			pixel_rate =
+				bdw_adjust_min_pipe_pixel_rate(crtc_state,
+							       pixel_rate);
+
+		intel_state->min_pixclk[i] = pixel_rate;
+	}
+
+	for_each_pipe(dev_priv, pipe)
+		max_pixel_rate = max(intel_state->min_pixclk[pipe],
+				     max_pixel_rate);
+
+	return max_pixel_rate;
+}
+
+static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
+{
+	struct drm_device *dev = state->dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	int max_pixclk = intel_max_pixel_rate(state);
+	struct intel_atomic_state *intel_state =
+		to_intel_atomic_state(state);
+
+	intel_state->cdclk = intel_state->dev_cdclk =
+		vlv_calc_cdclk(dev_priv, max_pixclk);
+
+	if (!intel_state->active_crtcs)
+		intel_state->dev_cdclk = vlv_calc_cdclk(dev_priv, 0);
+
+	return 0;
+}
+
+static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = old_state->dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_state);
+	unsigned int req_cdclk = old_intel_state->dev_cdclk;
+
+	/*
+	 * FIXME: We can end up here with all power domains off, yet
+	 * with a CDCLK frequency other than the minimum. To account
+	 * for this take the PIPE-A power domain, which covers the HW
+	 * blocks needed for the following programming. This can be
+	 * removed once it's guaranteed that we get here either with
+	 * the minimum CDCLK set, or the required power domains
+	 * enabled.
+	 */
+	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
+
+	if (IS_CHERRYVIEW(dev_priv))
+		chv_set_cdclk(dev, req_cdclk);
+	else
+		vlv_set_cdclk(dev, req_cdclk);
+
+	vlv_program_pfi_credits(dev_priv);
+
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
+}
+
+static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->dev);
+	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+	int max_pixclk = intel_max_pixel_rate(state);
+	int cdclk;
+
+	/*
+	 * FIXME should also account for plane ratio
+	 * once 64bpp pixel formats are supported.
+	 */
+	cdclk = bdw_calc_cdclk(max_pixclk);
+
+	if (cdclk > dev_priv->max_cdclk_freq) {
+		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+			      cdclk, dev_priv->max_cdclk_freq);
+		return -EINVAL;
+	}
+
+	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
+	if (!intel_state->active_crtcs)
+		intel_state->dev_cdclk = bdw_calc_cdclk(0);
+
+	return 0;
+}
+
+static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = old_state->dev;
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_state);
+	unsigned int req_cdclk = old_intel_state->dev_cdclk;
+
+	bdw_set_cdclk(dev, req_cdclk);
+}
+
+static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
+{
+	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+	struct drm_i915_private *dev_priv = to_i915(state->dev);
+	const int max_pixclk = intel_max_pixel_rate(state);
+	int vco = intel_state->cdclk_pll_vco;
+	int cdclk;
+
+	/*
+	 * FIXME should also account for plane ratio
+	 * once 64bpp pixel formats are supported.
+	 */
+	cdclk = skl_calc_cdclk(max_pixclk, vco);
+
+	/*
+	 * FIXME move the cdclk caclulation to
+	 * compute_config() so we can fail gracegully.
+	 */
+	if (cdclk > dev_priv->max_cdclk_freq) {
+		DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+			  cdclk, dev_priv->max_cdclk_freq);
+		cdclk = dev_priv->max_cdclk_freq;
+	}
+
+	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
+	if (!intel_state->active_crtcs)
+		intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
+
+	return 0;
+}
+
+static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
+	struct intel_atomic_state *intel_state =
+		to_intel_atomic_state(old_state);
+	unsigned int req_cdclk = intel_state->dev_cdclk;
+	unsigned int req_vco = intel_state->cdclk_pll_vco;
+
+	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
+}
+
+static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->dev);
+	int max_pixclk = intel_max_pixel_rate(state);
+	struct intel_atomic_state *intel_state =
+		to_intel_atomic_state(state);
+	int cdclk;
+
+	if (IS_GEMINILAKE(dev_priv))
+		cdclk = glk_calc_cdclk(max_pixclk);
+	else
+		cdclk = bxt_calc_cdclk(max_pixclk);
+
+	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
+
+	if (!intel_state->active_crtcs) {
+		if (IS_GEMINILAKE(dev_priv))
+			cdclk = glk_calc_cdclk(0);
+		else
+			cdclk = bxt_calc_cdclk(0);
+
+		intel_state->dev_cdclk = cdclk;
+	}
+
+	return 0;
+}
+
+static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
+{
+	struct drm_device *dev = old_state->dev;
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_state);
+	unsigned int req_cdclk = old_intel_state->dev_cdclk;
+
+	bxt_set_cdclk(to_i915(dev), req_cdclk);
+}
+
+static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
+{
+	int max_cdclk_freq = dev_priv->max_cdclk_freq;
+
+	if (IS_GEMINILAKE(dev_priv))
+		return 2 * max_cdclk_freq;
+	else if (INTEL_INFO(dev_priv)->gen >= 9 ||
+		 IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+		return max_cdclk_freq;
+	else if (IS_CHERRYVIEW(dev_priv))
+		return max_cdclk_freq*95/100;
+	else if (INTEL_INFO(dev_priv)->gen < 4)
+		return 2*max_cdclk_freq*90/100;
+	else
+		return max_cdclk_freq*90/100;
+}
+
+void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
+{
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+		u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
+		int max_cdclk, vco;
+
+		vco = dev_priv->skl_preferred_vco_freq;
+		WARN_ON(vco != 8100000 && vco != 8640000);
+
+		/*
+		 * Use the lower (vco 8640) cdclk values as a
+		 * first guess. skl_calc_cdclk() will correct it
+		 * if the preferred vco is 8100 instead.
+		 */
+		if (limit == SKL_DFSM_CDCLK_LIMIT_675)
+			max_cdclk = 617143;
+		else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
+			max_cdclk = 540000;
+		else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
+			max_cdclk = 432000;
+		else
+			max_cdclk = 308571;
+
+		dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
+	} else if (IS_GEMINILAKE(dev_priv)) {
+		dev_priv->max_cdclk_freq = 316800;
+	} else if (IS_BROXTON(dev_priv)) {
+		dev_priv->max_cdclk_freq = 624000;
+	} else if (IS_BROADWELL(dev_priv))  {
+		/*
+		 * FIXME with extra cooling we can allow
+		 * 540 MHz for ULX and 675 Mhz for ULT.
+		 * How can we know if extra cooling is
+		 * available? PCI ID, VTB, something else?
+		 */
+		if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
+			dev_priv->max_cdclk_freq = 450000;
+		else if (IS_BDW_ULX(dev_priv))
+			dev_priv->max_cdclk_freq = 450000;
+		else if (IS_BDW_ULT(dev_priv))
+			dev_priv->max_cdclk_freq = 540000;
+		else
+			dev_priv->max_cdclk_freq = 675000;
+	} else if (IS_CHERRYVIEW(dev_priv)) {
+		dev_priv->max_cdclk_freq = 320000;
+	} else if (IS_VALLEYVIEW(dev_priv)) {
+		dev_priv->max_cdclk_freq = 400000;
+	} else {
+		/* otherwise assume cdclk is fixed */
+		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
+	}
+
+	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
+
+	DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
+			 dev_priv->max_cdclk_freq);
+
+	DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
+			 dev_priv->max_dotclk_freq);
+}
+
+void intel_update_cdclk(struct drm_i915_private *dev_priv)
+{
+	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
+				 dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
+				 dev_priv->cdclk_pll.ref);
+	else
+		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
+				 dev_priv->cdclk_freq);
+
+	/*
+	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
+	 * Programmng [sic] note: bit[9:2] should be programmed to the number
+	 * of cdclk that generates 4MHz reference clock freq which is used to
+	 * generate GMBus clock. This will vary with the cdclk freq.
+	 */
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		I915_WRITE(GMBUSFREQ_VLV,
+			   DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
+}
+
+static int pch_rawclk(struct drm_i915_private *dev_priv)
+{
+	return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
+}
+
+static int vlv_hrawclk(struct drm_i915_private *dev_priv)
+{
+	/* RAWCLK_FREQ_VLV register updated from power well code */
+	return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
+				      CCK_DISPLAY_REF_CLOCK_CONTROL);
+}
+
+static int g4x_hrawclk(struct drm_i915_private *dev_priv)
+{
+	uint32_t clkcfg;
+
+	/* hrawclock is 1/4 the FSB frequency */
+	clkcfg = I915_READ(CLKCFG);
+	switch (clkcfg & CLKCFG_FSB_MASK) {
+	case CLKCFG_FSB_400:
+		return 100000;
+	case CLKCFG_FSB_533:
+		return 133333;
+	case CLKCFG_FSB_667:
+		return 166667;
+	case CLKCFG_FSB_800:
+		return 200000;
+	case CLKCFG_FSB_1067:
+		return 266667;
+	case CLKCFG_FSB_1333:
+		return 333333;
+	/* these two are just a guess; one of them might be right */
+	case CLKCFG_FSB_1600:
+	case CLKCFG_FSB_1600_ALT:
+		return 400000;
+	default:
+		return 133333;
+	}
+}
+
+void intel_update_rawclk(struct drm_i915_private *dev_priv)
+{
+	if (HAS_PCH_SPLIT(dev_priv))
+		dev_priv->rawclk_freq = pch_rawclk(dev_priv);
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		dev_priv->rawclk_freq = vlv_hrawclk(dev_priv);
+	else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
+		dev_priv->rawclk_freq = g4x_hrawclk(dev_priv);
+	else
+		/* no rawclk on other platforms, or no need to know it */
+		return;
+
+	DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
+}
+
+void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
+{
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		dev_priv->display.modeset_commit_cdclk =
+			vlv_modeset_commit_cdclk;
+		dev_priv->display.modeset_calc_cdclk =
+			vlv_modeset_calc_cdclk;
+	} else if (IS_BROADWELL(dev_priv)) {
+		dev_priv->display.modeset_commit_cdclk =
+			bdw_modeset_commit_cdclk;
+		dev_priv->display.modeset_calc_cdclk =
+			bdw_modeset_calc_cdclk;
+	} else if (IS_GEN9_LP(dev_priv)) {
+		dev_priv->display.modeset_commit_cdclk =
+			bxt_modeset_commit_cdclk;
+		dev_priv->display.modeset_calc_cdclk =
+			bxt_modeset_calc_cdclk;
+	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+		dev_priv->display.modeset_commit_cdclk =
+			skl_modeset_commit_cdclk;
+		dev_priv->display.modeset_calc_cdclk =
+			skl_modeset_calc_cdclk;
+	}
+
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+		dev_priv->display.get_cdclk = skl_get_cdclk;
+	else if (IS_GEN9_LP(dev_priv))
+		dev_priv->display.get_cdclk = bxt_get_cdclk;
+	else if (IS_BROADWELL(dev_priv))
+		dev_priv->display.get_cdclk = bdw_get_cdclk;
+	else if (IS_HASWELL(dev_priv))
+		dev_priv->display.get_cdclk = hsw_get_cdclk;
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		dev_priv->display.get_cdclk = vlv_get_cdclk;
+	else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
+		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
+	else if (IS_GEN5(dev_priv))
+		dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
+	else if (IS_GM45(dev_priv))
+		dev_priv->display.get_cdclk = gm45_get_cdclk;
+	else if (IS_G4X(dev_priv))
+		dev_priv->display.get_cdclk = g33_get_cdclk;
+	else if (IS_I965GM(dev_priv))
+		dev_priv->display.get_cdclk = i965gm_get_cdclk;
+	else if (IS_I965G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
+	else if (IS_PINEVIEW(dev_priv))
+		dev_priv->display.get_cdclk = pnv_get_cdclk;
+	else if (IS_G33(dev_priv))
+		dev_priv->display.get_cdclk = g33_get_cdclk;
+	else if (IS_I945GM(dev_priv))
+		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
+	else if (IS_I945G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
+	else if (IS_I915GM(dev_priv))
+		dev_priv->display.get_cdclk = i915gm_get_cdclk;
+	else if (IS_I915G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
+	else if (IS_I865G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
+	else if (IS_I85X(dev_priv))
+		dev_priv->display.get_cdclk = i85x_get_cdclk;
+	else if (IS_I845G(dev_priv))
+		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
+	else { /* 830 */
+		WARN(!IS_I830(dev_priv),
+		     "Unknown platform. Assuming 133 MHz CDCLK\n");
+		dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
+	}
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 29f91e799272..519e5d663c5f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -123,9 +123,6 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
 static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
-static int intel_max_pixel_rate(struct drm_atomic_state *state);
-static int glk_calc_cdclk(int max_pixclk);
-static int bxt_calc_cdclk(int max_pixclk);
 
 struct intel_limit {
 	struct {
@@ -171,8 +168,8 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
 	return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
 }
 
-static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
-				  const char *name, u32 reg)
+int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
+			   const char *name, u32 reg)
 {
 	if (dev_priv->hpll_freq == 0)
 		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
@@ -181,63 +178,6 @@ static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
 				 dev_priv->hpll_freq);
 }
 
-static int
-intel_pch_rawclk(struct drm_i915_private *dev_priv)
-{
-	return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
-}
-
-static int
-intel_vlv_hrawclk(struct drm_i915_private *dev_priv)
-{
-	/* RAWCLK_FREQ_VLV register updated from power well code */
-	return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
-				      CCK_DISPLAY_REF_CLOCK_CONTROL);
-}
-
-static int
-intel_g4x_hrawclk(struct drm_i915_private *dev_priv)
-{
-	uint32_t clkcfg;
-
-	/* hrawclock is 1/4 the FSB frequency */
-	clkcfg = I915_READ(CLKCFG);
-	switch (clkcfg & CLKCFG_FSB_MASK) {
-	case CLKCFG_FSB_400:
-		return 100000;
-	case CLKCFG_FSB_533:
-		return 133333;
-	case CLKCFG_FSB_667:
-		return 166667;
-	case CLKCFG_FSB_800:
-		return 200000;
-	case CLKCFG_FSB_1067:
-		return 266667;
-	case CLKCFG_FSB_1333:
-		return 333333;
-	/* these two are just a guess; one of them might be right */
-	case CLKCFG_FSB_1600:
-	case CLKCFG_FSB_1600_ALT:
-		return 400000;
-	default:
-		return 133333;
-	}
-}
-
-void intel_update_rawclk(struct drm_i915_private *dev_priv)
-{
-	if (HAS_PCH_SPLIT(dev_priv))
-		dev_priv->rawclk_freq = intel_pch_rawclk(dev_priv);
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		dev_priv->rawclk_freq = intel_vlv_hrawclk(dev_priv);
-	else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
-		dev_priv->rawclk_freq = intel_g4x_hrawclk(dev_priv);
-	else
-		return; /* no rawclk on other platforms, or no need to know it */
-
-	DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
-}
-
 static void intel_update_czclk(struct drm_i915_private *dev_priv)
 {
 	if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
@@ -5791,1092 +5731,210 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
 		intel_display_power_put(dev_priv, domain);
 }
 
-static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
+static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
+				   struct drm_atomic_state *old_state)
 {
-	int max_cdclk_freq = dev_priv->max_cdclk_freq;
+	struct drm_crtc *crtc = pipe_config->base.crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
 
-	if (IS_GEMINILAKE(dev_priv))
-		return 2 * max_cdclk_freq;
-	else if (INTEL_INFO(dev_priv)->gen >= 9 ||
-		 IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-		return max_cdclk_freq;
-	else if (IS_CHERRYVIEW(dev_priv))
-		return max_cdclk_freq*95/100;
-	else if (INTEL_INFO(dev_priv)->gen < 4)
-		return 2*max_cdclk_freq*90/100;
-	else
-		return max_cdclk_freq*90/100;
-}
+	if (WARN_ON(intel_crtc->active))
+		return;
 
-static int skl_calc_cdclk(int max_pixclk, int vco);
+	if (intel_crtc_has_dp_encoder(intel_crtc->config))
+		intel_dp_set_m_n(intel_crtc, M1_N1);
 
-static void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
-{
-	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-		u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
-		int max_cdclk, vco;
+	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_src_size(intel_crtc);
 
-		vco = dev_priv->skl_preferred_vco_freq;
-		WARN_ON(vco != 8100000 && vco != 8640000);
+	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+		struct drm_i915_private *dev_priv = to_i915(dev);
 
-		/*
-		 * Use the lower (vco 8640) cdclk values as a
-		 * first guess. skl_calc_cdclk() will correct it
-		 * if the preferred vco is 8100 instead.
-		 */
-		if (limit == SKL_DFSM_CDCLK_LIMIT_675)
-			max_cdclk = 617143;
-		else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
-			max_cdclk = 540000;
-		else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
-			max_cdclk = 432000;
-		else
-			max_cdclk = 308571;
-
-		dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
-	} else if (IS_GEMINILAKE(dev_priv)) {
-		dev_priv->max_cdclk_freq = 316800;
-	} else if (IS_BROXTON(dev_priv)) {
-		dev_priv->max_cdclk_freq = 624000;
-	} else if (IS_BROADWELL(dev_priv))  {
-		/*
-		 * FIXME with extra cooling we can allow
-		 * 540 MHz for ULX and 675 Mhz for ULT.
-		 * How can we know if extra cooling is
-		 * available? PCI ID, VTB, something else?
-		 */
-		if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
-			dev_priv->max_cdclk_freq = 450000;
-		else if (IS_BDW_ULX(dev_priv))
-			dev_priv->max_cdclk_freq = 450000;
-		else if (IS_BDW_ULT(dev_priv))
-			dev_priv->max_cdclk_freq = 540000;
-		else
-			dev_priv->max_cdclk_freq = 675000;
-	} else if (IS_CHERRYVIEW(dev_priv)) {
-		dev_priv->max_cdclk_freq = 320000;
-	} else if (IS_VALLEYVIEW(dev_priv)) {
-		dev_priv->max_cdclk_freq = 400000;
-	} else {
-		/* otherwise assume cdclk is fixed */
-		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
+		I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
+		I915_WRITE(CHV_CANVAS(pipe), 0);
 	}
 
-	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
-
-	DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
-			 dev_priv->max_cdclk_freq);
-
-	DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
-			 dev_priv->max_dotclk_freq);
-}
-
-static void intel_update_cdclk(struct drm_i915_private *dev_priv)
-{
-	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
-
-	if (INTEL_GEN(dev_priv) >= 9)
-		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
-				 dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
-				 dev_priv->cdclk_pll.ref);
-	else
-		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
-				 dev_priv->cdclk_freq);
-
-	/*
-	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
-	 * Programmng [sic] note: bit[9:2] should be programmed to the number
-	 * of cdclk that generates 4MHz reference clock freq which is used to
-	 * generate GMBus clock. This will vary with the cdclk freq.
-	 */
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
-}
+	i9xx_set_pipeconf(intel_crtc);
 
-/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
-static int skl_cdclk_decimal(int cdclk)
-{
-	return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
-}
+	intel_crtc->active = true;
 
-static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
-{
-	int ratio;
+	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
-	if (cdclk == dev_priv->cdclk_pll.ref)
-		return 0;
+	intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
 
-	switch (cdclk) {
-	default:
-		MISSING_CASE(cdclk);
-	case 144000:
-	case 288000:
-	case 384000:
-	case 576000:
-		ratio = 60;
-		break;
-	case 624000:
-		ratio = 65;
-		break;
+	if (IS_CHERRYVIEW(dev_priv)) {
+		chv_prepare_pll(intel_crtc, intel_crtc->config);
+		chv_enable_pll(intel_crtc, intel_crtc->config);
+	} else {
+		vlv_prepare_pll(intel_crtc, intel_crtc->config);
+		vlv_enable_pll(intel_crtc, intel_crtc->config);
 	}
 
-	return dev_priv->cdclk_pll.ref * ratio;
-}
+	intel_encoders_pre_enable(crtc, pipe_config, old_state);
 
-static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
-{
-	int ratio;
+	i9xx_pfit_enable(intel_crtc);
 
-	if (cdclk == dev_priv->cdclk_pll.ref)
-		return 0;
+	intel_color_load_luts(&pipe_config->base);
 
-	switch (cdclk) {
-	default:
-		MISSING_CASE(cdclk);
-	case  79200:
-	case 158400:
-	case 316800:
-		ratio = 33;
-		break;
-	}
+	intel_update_watermarks(intel_crtc);
+	intel_enable_pipe(intel_crtc);
+
+	assert_vblank_disabled(crtc);
+	drm_crtc_vblank_on(crtc);
 
-	return dev_priv->cdclk_pll.ref * ratio;
+	intel_encoders_enable(crtc, pipe_config, old_state);
 }
 
-static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
+static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
 {
-	I915_WRITE(BXT_DE_PLL_ENABLE, 0);
-
-	/* Timeout 200us */
-	if (intel_wait_for_register(dev_priv,
-				    BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
-				    1))
-		DRM_ERROR("timeout waiting for DE PLL unlock\n");
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 
-	dev_priv->cdclk_pll.vco = 0;
+	I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
+	I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
 }
 
-static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
+static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
+			     struct drm_atomic_state *old_state)
 {
-	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
-	u32 val;
+	struct drm_crtc *crtc = pipe_config->base.crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum pipe pipe = intel_crtc->pipe;
 
-	val = I915_READ(BXT_DE_PLL_CTL);
-	val &= ~BXT_DE_PLL_RATIO_MASK;
-	val |= BXT_DE_PLL_RATIO(ratio);
-	I915_WRITE(BXT_DE_PLL_CTL, val);
+	if (WARN_ON(intel_crtc->active))
+		return;
 
-	I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
+	i9xx_set_pll_dividers(intel_crtc);
 
-	/* Timeout 200us */
-	if (intel_wait_for_register(dev_priv,
-				    BXT_DE_PLL_ENABLE,
-				    BXT_DE_PLL_LOCK,
-				    BXT_DE_PLL_LOCK,
-				    1))
-		DRM_ERROR("timeout waiting for DE PLL lock\n");
+	if (intel_crtc_has_dp_encoder(intel_crtc->config))
+		intel_dp_set_m_n(intel_crtc, M1_N1);
 
-	dev_priv->cdclk_pll.vco = vco;
-}
+	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_src_size(intel_crtc);
 
-static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
-{
-	u32 val, divider;
-	int vco, ret;
+	i9xx_set_pipeconf(intel_crtc);
 
-	if (IS_GEMINILAKE(dev_priv))
-		vco = glk_de_pll_vco(dev_priv, cdclk);
-	else
-		vco = bxt_de_pll_vco(dev_priv, cdclk);
+	intel_crtc->active = true;
 
-	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
+	if (!IS_GEN2(dev_priv))
+		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
-	/* cdclk = vco / 2 / div{1,1.5,2,4} */
-	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
-	case 8:
-		divider = BXT_CDCLK_CD2X_DIV_SEL_4;
-		break;
-	case 4:
-		divider = BXT_CDCLK_CD2X_DIV_SEL_2;
-		break;
-	case 3:
-		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
-		divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
-		break;
-	case 2:
-		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
-		break;
-	default:
-		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
-		WARN_ON(vco != 0);
+	intel_encoders_pre_enable(crtc, pipe_config, old_state);
 
-		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
-		break;
-	}
+	i9xx_enable_pll(intel_crtc);
 
-	/* Inform power controller of upcoming frequency change */
-	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
-				      0x80000000);
-	mutex_unlock(&dev_priv->rps.hw_lock);
+	i9xx_pfit_enable(intel_crtc);
 
-	if (ret) {
-		DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n",
-			  ret, cdclk);
-		return;
-	}
+	intel_color_load_luts(&pipe_config->base);
 
-	if (dev_priv->cdclk_pll.vco != 0 &&
-	    dev_priv->cdclk_pll.vco != vco)
-		bxt_de_pll_disable(dev_priv);
+	intel_update_watermarks(intel_crtc);
+	intel_enable_pipe(intel_crtc);
 
-	if (dev_priv->cdclk_pll.vco != vco)
-		bxt_de_pll_enable(dev_priv, vco);
+	assert_vblank_disabled(crtc);
+	drm_crtc_vblank_on(crtc);
 
-	val = divider | skl_cdclk_decimal(cdclk);
-	/*
-	 * FIXME if only the cd2x divider needs changing, it could be done
-	 * without shutting off the pipe (if only one pipe is active).
-	 */
-	val |= BXT_CDCLK_CD2X_PIPE_NONE;
-	/*
-	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
-	 * enable otherwise.
-	 */
-	if (cdclk >= 500000)
-		val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
-	I915_WRITE(CDCLK_CTL, val);
+	intel_encoders_enable(crtc, pipe_config, old_state);
+}
 
-	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
-				      DIV_ROUND_UP(cdclk, 25000));
-	mutex_unlock(&dev_priv->rps.hw_lock);
+static void i9xx_pfit_disable(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 
-	if (ret) {
-		DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
-			  ret, cdclk);
+	if (!crtc->config->gmch_pfit.control)
 		return;
-	}
 
-	intel_update_cdclk(dev_priv);
+	assert_pipe_disabled(dev_priv, crtc->pipe);
+
+	DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
+			 I915_READ(PFIT_CONTROL));
+	I915_WRITE(PFIT_CONTROL, 0);
 }
 
-static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
+static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
+			      struct drm_atomic_state *old_state)
 {
-	u32 cdctl, expected;
-
-	intel_update_cdclk(dev_priv);
-
-	if (dev_priv->cdclk_pll.vco == 0 ||
-	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
-		goto sanitize;
-
-	/* DPLL okay; verify the cdclock
-	 *
-	 * Some BIOS versions leave an incorrect decimal frequency value and
-	 * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
-	 * so sanitize this register.
-	 */
-	cdctl = I915_READ(CDCLK_CTL);
-	/*
-	 * Let's ignore the pipe field, since BIOS could have configured the
-	 * dividers both synching to an active pipe, or asynchronously
-	 * (PIPE_NONE).
-	 */
-	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
+	struct drm_crtc *crtc = old_crtc_state->base.crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
 
-	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
-		   skl_cdclk_decimal(dev_priv->cdclk_freq);
 	/*
-	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
-	 * enable otherwise.
+	 * On gen2 planes are double buffered but the pipe isn't, so we must
+	 * wait for planes to fully turn off before disabling the pipe.
 	 */
-	if (dev_priv->cdclk_freq >= 500000)
-		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
-
-	if (cdctl == expected)
-		/* All well; nothing to sanitize */
-		return;
+	if (IS_GEN2(dev_priv))
+		intel_wait_for_vblank(dev_priv, pipe);
 
-sanitize:
-	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
+	intel_encoders_disable(crtc, old_crtc_state, old_state);
 
-	/* force cdclk programming */
-	dev_priv->cdclk_freq = 0;
+	drm_crtc_vblank_off(crtc);
+	assert_vblank_disabled(crtc);
 
-	/* force full PLL disable + enable */
-	dev_priv->cdclk_pll.vco = -1;
-}
+	intel_disable_pipe(intel_crtc);
 
-void bxt_init_cdclk(struct drm_i915_private *dev_priv)
-{
-	int cdclk;
+	i9xx_pfit_disable(intel_crtc);
 
-	bxt_sanitize_cdclk(dev_priv);
+	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
 
-	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
-		return;
+	if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
+		if (IS_CHERRYVIEW(dev_priv))
+			chv_disable_pll(dev_priv, pipe);
+		else if (IS_VALLEYVIEW(dev_priv))
+			vlv_disable_pll(dev_priv, pipe);
+		else
+			i9xx_disable_pll(intel_crtc);
+	}
 
-	/*
-	 * FIXME:
-	 * - The initial CDCLK needs to be read from VBT.
-	 *   Need to make this change after VBT has changes for BXT.
-	 */
-	if (IS_GEMINILAKE(dev_priv))
-		cdclk = glk_calc_cdclk(0);
-	else
-		cdclk = bxt_calc_cdclk(0);
+	intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
 
-	bxt_set_cdclk(dev_priv, cdclk);
+	if (!IS_GEN2(dev_priv))
+		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 }
 
-void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
+static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
 {
-	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
-}
+	struct intel_encoder *encoder;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+	enum intel_display_power_domain domain;
+	unsigned long domains;
+	struct drm_atomic_state *state;
+	struct intel_crtc_state *crtc_state;
+	int ret;
 
-static int skl_calc_cdclk(int max_pixclk, int vco)
-{
-	if (vco == 8640000) {
-		if (max_pixclk > 540000)
-			return 617143;
-		else if (max_pixclk > 432000)
-			return 540000;
-		else if (max_pixclk > 308571)
-			return 432000;
-		else
-			return 308571;
-	} else {
-		if (max_pixclk > 540000)
-			return 675000;
-		else if (max_pixclk > 450000)
-			return 540000;
-		else if (max_pixclk > 337500)
-			return 450000;
-		else
-			return 337500;
-	}
-}
+	if (!intel_crtc->active)
+		return;
 
-static void
-skl_dpll0_update(struct drm_i915_private *dev_priv)
-{
-	u32 val;
+	if (to_intel_plane_state(crtc->primary->state)->base.visible) {
+		WARN_ON(intel_crtc->flip_work);
 
-	dev_priv->cdclk_pll.ref = 24000;
-	dev_priv->cdclk_pll.vco = 0;
+		intel_pre_disable_primary_noatomic(crtc);
 
-	val = I915_READ(LCPLL1_CTL);
-	if ((val & LCPLL_PLL_ENABLE) == 0)
-		return;
+		intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
+		to_intel_plane_state(crtc->primary->state)->base.visible = false;
+	}
 
-	if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
-		return;
+	state = drm_atomic_state_alloc(crtc->dev);
+	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
 
-	val = I915_READ(DPLL_CTRL1);
+	/* Everything's already locked, -EDEADLK can't happen. */
+	crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
+	ret = drm_atomic_add_affected_connectors(state, crtc);
 
-	if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
-			    DPLL_CTRL1_SSC(SKL_DPLL0) |
-			    DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
-		    DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
-		return;
+	WARN_ON(IS_ERR(crtc_state) || ret);
 
-	switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
-	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
-	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
-	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
-	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
-		dev_priv->cdclk_pll.vco = 8100000;
-		break;
-	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
-	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
-		dev_priv->cdclk_pll.vco = 8640000;
-		break;
-	default:
-		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
-		break;
-	}
-}
+	dev_priv->display.crtc_disable(crtc_state, state);
 
-void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
-{
-	bool changed = dev_priv->skl_preferred_vco_freq != vco;
+	drm_atomic_state_put(state);
 
-	dev_priv->skl_preferred_vco_freq = vco;
-
-	if (changed)
-		intel_update_max_cdclk(dev_priv);
-}
-
-static void
-skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
-{
-	int min_cdclk = skl_calc_cdclk(0, vco);
-	u32 val;
-
-	WARN_ON(vco != 8100000 && vco != 8640000);
-
-	/* select the minimum CDCLK before enabling DPLL 0 */
-	val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
-	I915_WRITE(CDCLK_CTL, val);
-	POSTING_READ(CDCLK_CTL);
-
-	/*
-	 * We always enable DPLL0 with the lowest link rate possible, but still
-	 * taking into account the VCO required to operate the eDP panel at the
-	 * desired frequency. The usual DP link rates operate with a VCO of
-	 * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
-	 * The modeset code is responsible for the selection of the exact link
-	 * rate later on, with the constraint of choosing a frequency that
-	 * works with vco.
-	 */
-	val = I915_READ(DPLL_CTRL1);
-
-	val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0) |
-		 DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
-	val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
-	if (vco == 8640000)
-		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
-					    SKL_DPLL0);
-	else
-		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
-					    SKL_DPLL0);
-
-	I915_WRITE(DPLL_CTRL1, val);
-	POSTING_READ(DPLL_CTRL1);
-
-	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
-
-	if (intel_wait_for_register(dev_priv,
-				    LCPLL1_CTL, LCPLL_PLL_LOCK, LCPLL_PLL_LOCK,
-				    5))
-		DRM_ERROR("DPLL0 not locked\n");
-
-	dev_priv->cdclk_pll.vco = vco;
-
-	/* We'll want to keep using the current vco from now on. */
-	skl_set_preferred_cdclk_vco(dev_priv, vco);
-}
-
-static void
-skl_dpll0_disable(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
-	if (intel_wait_for_register(dev_priv,
-				   LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
-				   1))
-		DRM_ERROR("Couldn't disable DPLL0\n");
-
-	dev_priv->cdclk_pll.vco = 0;
-}
-
-static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
-{
-	u32 freq_select, pcu_ack;
-	int ret;
-
-	WARN_ON((cdclk == 24000) != (vco == 0));
-
-	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
-
-	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
-				SKL_CDCLK_PREPARE_FOR_CHANGE,
-				SKL_CDCLK_READY_FOR_CHANGE,
-				SKL_CDCLK_READY_FOR_CHANGE, 3);
-	mutex_unlock(&dev_priv->rps.hw_lock);
-	if (ret) {
-		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
-			  ret);
-		return;
-	}
-
-	/* set CDCLK_CTL */
-	switch (cdclk) {
-	case 450000:
-	case 432000:
-		freq_select = CDCLK_FREQ_450_432;
-		pcu_ack = 1;
-		break;
-	case 540000:
-		freq_select = CDCLK_FREQ_540;
-		pcu_ack = 2;
-		break;
-	case 308571:
-	case 337500:
-	default:
-		freq_select = CDCLK_FREQ_337_308;
-		pcu_ack = 0;
-		break;
-	case 617143:
-	case 675000:
-		freq_select = CDCLK_FREQ_675_617;
-		pcu_ack = 3;
-		break;
-	}
-
-	if (dev_priv->cdclk_pll.vco != 0 &&
-	    dev_priv->cdclk_pll.vco != vco)
-		skl_dpll0_disable(dev_priv);
-
-	if (dev_priv->cdclk_pll.vco != vco)
-		skl_dpll0_enable(dev_priv, vco);
-
-	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
-	POSTING_READ(CDCLK_CTL);
-
-	/* inform PCU of the change */
-	mutex_lock(&dev_priv->rps.hw_lock);
-	sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
-	mutex_unlock(&dev_priv->rps.hw_lock);
-
-	intel_update_cdclk(dev_priv);
-}
-
-static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
-
-void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
-{
-	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
-}
-
-void skl_init_cdclk(struct drm_i915_private *dev_priv)
-{
-	int cdclk, vco;
-
-	skl_sanitize_cdclk(dev_priv);
-
-	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
-		/*
-		 * Use the current vco as our initial
-		 * guess as to what the preferred vco is.
-		 */
-		if (dev_priv->skl_preferred_vco_freq == 0)
-			skl_set_preferred_cdclk_vco(dev_priv,
-						    dev_priv->cdclk_pll.vco);
-		return;
-	}
-
-	vco = dev_priv->skl_preferred_vco_freq;
-	if (vco == 0)
-		vco = 8100000;
-	cdclk = skl_calc_cdclk(0, vco);
-
-	skl_set_cdclk(dev_priv, cdclk, vco);
-}
-
-static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
-{
-	uint32_t cdctl, expected;
-
-	/*
-	 * check if the pre-os intialized the display
-	 * There is SWF18 scratchpad register defined which is set by the
-	 * pre-os which can be used by the OS drivers to check the status
-	 */
-	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
-		goto sanitize;
-
-	intel_update_cdclk(dev_priv);
-	/* Is PLL enabled and locked ? */
-	if (dev_priv->cdclk_pll.vco == 0 ||
-	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
-		goto sanitize;
-
-	/* DPLL okay; verify the cdclock
-	 *
-	 * Noticed in some instances that the freq selection is correct but
-	 * decimal part is programmed wrong from BIOS where pre-os does not
-	 * enable display. Verify the same as well.
-	 */
-	cdctl = I915_READ(CDCLK_CTL);
-	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
-		skl_cdclk_decimal(dev_priv->cdclk_freq);
-	if (cdctl == expected)
-		/* All well; nothing to sanitize */
-		return;
-
-sanitize:
-	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
-
-	/* force cdclk programming */
-	dev_priv->cdclk_freq = 0;
-	/* force full PLL disable + enable */
-	dev_priv->cdclk_pll.vco = -1;
-}
-
-/* Adjust CDclk dividers to allow high res or save power if possible */
-static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
-{
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	u32 val, cmd;
-
-	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
-
-	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
-		cmd = 2;
-	else if (cdclk == 266667)
-		cmd = 1;
-	else
-		cmd = 0;
-
-	mutex_lock(&dev_priv->rps.hw_lock);
-	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
-	val &= ~DSPFREQGUAR_MASK;
-	val |= (cmd << DSPFREQGUAR_SHIFT);
-	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
-	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
-		      DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
-		     50)) {
-		DRM_ERROR("timed out waiting for CDclk change\n");
-	}
-	mutex_unlock(&dev_priv->rps.hw_lock);
-
-	mutex_lock(&dev_priv->sb_lock);
-
-	if (cdclk == 400000) {
-		u32 divider;
-
-		divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
-
-		/* adjust cdclk divider */
-		val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
-		val &= ~CCK_FREQUENCY_VALUES;
-		val |= divider;
-		vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
-
-		if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
-			      CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
-			     50))
-			DRM_ERROR("timed out waiting for CDclk change\n");
-	}
-
-	/* adjust self-refresh exit latency value */
-	val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
-	val &= ~0x7f;
-
-	/*
-	 * For high bandwidth configs, we set a higher latency in the bunit
-	 * so that the core display fetch happens in time to avoid underruns.
-	 */
-	if (cdclk == 400000)
-		val |= 4500 / 250; /* 4.5 usec */
-	else
-		val |= 3000 / 250; /* 3.0 usec */
-	vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
-
-	mutex_unlock(&dev_priv->sb_lock);
-
-	intel_update_cdclk(dev_priv);
-}
-
-static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
-{
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	u32 val, cmd;
-
-	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
-
-	switch (cdclk) {
-	case 333333:
-	case 320000:
-	case 266667:
-	case 200000:
-		break;
-	default:
-		MISSING_CASE(cdclk);
-		return;
-	}
-
-	/*
-	 * Specs are full of misinformation, but testing on actual
-	 * hardware has shown that we just need to write the desired
-	 * CCK divider into the Punit register.
-	 */
-	cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
-
-	mutex_lock(&dev_priv->rps.hw_lock);
-	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
-	val &= ~DSPFREQGUAR_MASK_CHV;
-	val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
-	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
-	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
-		      DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
-		     50)) {
-		DRM_ERROR("timed out waiting for CDclk change\n");
-	}
-	mutex_unlock(&dev_priv->rps.hw_lock);
-
-	intel_update_cdclk(dev_priv);
-}
-
-static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
-				 int max_pixclk)
-{
-	int freq_320 = (dev_priv->hpll_freq <<  1) % 320000 != 0 ? 333333 : 320000;
-	int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
-
-	/*
-	 * Really only a few cases to deal with, as only 4 CDclks are supported:
-	 *   200MHz
-	 *   267MHz
-	 *   320/333MHz (depends on HPLL freq)
-	 *   400MHz (VLV only)
-	 * So we check to see whether we're above 90% (VLV) or 95% (CHV)
-	 * of the lower bin and adjust if needed.
-	 *
-	 * We seem to get an unstable or solid color picture at 200MHz.
-	 * Not sure what's wrong. For now use 200MHz only when all pipes
-	 * are off.
-	 */
-	if (!IS_CHERRYVIEW(dev_priv) &&
-	    max_pixclk > freq_320*limit/100)
-		return 400000;
-	else if (max_pixclk > 266667*limit/100)
-		return freq_320;
-	else if (max_pixclk > 0)
-		return 266667;
-	else
-		return 200000;
-}
-
-static int glk_calc_cdclk(int max_pixclk)
-{
-	if (max_pixclk > 2 * 158400)
-		return 316800;
-	else if (max_pixclk > 2 * 79200)
-		return 158400;
-	else
-		return 79200;
-}
-
-static int bxt_calc_cdclk(int max_pixclk)
-{
-	if (max_pixclk > 576000)
-		return 624000;
-	else if (max_pixclk > 384000)
-		return 576000;
-	else if (max_pixclk > 288000)
-		return 384000;
-	else if (max_pixclk > 144000)
-		return 288000;
-	else
-		return 144000;
-}
-
-static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
-{
-	struct drm_device *dev = state->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	int max_pixclk = intel_max_pixel_rate(state);
-	struct intel_atomic_state *intel_state =
-		to_intel_atomic_state(state);
-
-	intel_state->cdclk = intel_state->dev_cdclk =
-		valleyview_calc_cdclk(dev_priv, max_pixclk);
-
-	if (!intel_state->active_crtcs)
-		intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0);
-
-	return 0;
-}
-
-static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
-{
-	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	int max_pixclk = intel_max_pixel_rate(state);
-	struct intel_atomic_state *intel_state =
-		to_intel_atomic_state(state);
-	int cdclk;
-
-	if (IS_GEMINILAKE(dev_priv))
-		cdclk = glk_calc_cdclk(max_pixclk);
-	else
-		cdclk = bxt_calc_cdclk(max_pixclk);
-
-	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
-
-	if (!intel_state->active_crtcs) {
-		if (IS_GEMINILAKE(dev_priv))
-			cdclk = glk_calc_cdclk(0);
-		else
-			cdclk = bxt_calc_cdclk(0);
-
-		intel_state->dev_cdclk = cdclk;
-	}
-
-	return 0;
-}
-
-static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
-{
-	unsigned int credits, default_credits;
-
-	if (IS_CHERRYVIEW(dev_priv))
-		default_credits = PFI_CREDIT(12);
-	else
-		default_credits = PFI_CREDIT(8);
-
-	if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
-		/* CHV suggested value is 31 or 63 */
-		if (IS_CHERRYVIEW(dev_priv))
-			credits = PFI_CREDIT_63;
-		else
-			credits = PFI_CREDIT(15);
-	} else {
-		credits = default_credits;
-	}
-
-	/*
-	 * WA - write default credits before re-programming
-	 * FIXME: should we also set the resend bit here?
-	 */
-	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
-		   default_credits);
-
-	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
-		   credits | PFI_CREDIT_RESEND);
-
-	/*
-	 * FIXME is this guaranteed to clear
-	 * immediately or should we poll for it?
-	 */
-	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
-}
-
-static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_device *dev = old_state->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_atomic_state *old_intel_state =
-		to_intel_atomic_state(old_state);
-	unsigned req_cdclk = old_intel_state->dev_cdclk;
-
-	/*
-	 * FIXME: We can end up here with all power domains off, yet
-	 * with a CDCLK frequency other than the minimum. To account
-	 * for this take the PIPE-A power domain, which covers the HW
-	 * blocks needed for the following programming. This can be
-	 * removed once it's guaranteed that we get here either with
-	 * the minimum CDCLK set, or the required power domains
-	 * enabled.
-	 */
-	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
-
-	if (IS_CHERRYVIEW(dev_priv))
-		cherryview_set_cdclk(dev, req_cdclk);
-	else
-		valleyview_set_cdclk(dev, req_cdclk);
-
-	vlv_program_pfi_credits(dev_priv);
-
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
-}
-
-static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
-				   struct drm_atomic_state *old_state)
-{
-	struct drm_crtc *crtc = pipe_config->base.crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-
-	if (WARN_ON(intel_crtc->active))
-		return;
-
-	if (intel_crtc_has_dp_encoder(intel_crtc->config))
-		intel_dp_set_m_n(intel_crtc, M1_N1);
-
-	intel_set_pipe_timings(intel_crtc);
-	intel_set_pipe_src_size(intel_crtc);
-
-	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
-		struct drm_i915_private *dev_priv = to_i915(dev);
-
-		I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
-		I915_WRITE(CHV_CANVAS(pipe), 0);
-	}
-
-	i9xx_set_pipeconf(intel_crtc);
-
-	intel_crtc->active = true;
-
-	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
-	intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
-
-	if (IS_CHERRYVIEW(dev_priv)) {
-		chv_prepare_pll(intel_crtc, intel_crtc->config);
-		chv_enable_pll(intel_crtc, intel_crtc->config);
-	} else {
-		vlv_prepare_pll(intel_crtc, intel_crtc->config);
-		vlv_enable_pll(intel_crtc, intel_crtc->config);
-	}
-
-	intel_encoders_pre_enable(crtc, pipe_config, old_state);
-
-	i9xx_pfit_enable(intel_crtc);
-
-	intel_color_load_luts(&pipe_config->base);
-
-	intel_update_watermarks(intel_crtc);
-	intel_enable_pipe(intel_crtc);
-
-	assert_vblank_disabled(crtc);
-	drm_crtc_vblank_on(crtc);
-
-	intel_encoders_enable(crtc, pipe_config, old_state);
-}
-
-static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
-	I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
-}
-
-static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
-			     struct drm_atomic_state *old_state)
-{
-	struct drm_crtc *crtc = pipe_config->base.crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	enum pipe pipe = intel_crtc->pipe;
-
-	if (WARN_ON(intel_crtc->active))
-		return;
-
-	i9xx_set_pll_dividers(intel_crtc);
-
-	if (intel_crtc_has_dp_encoder(intel_crtc->config))
-		intel_dp_set_m_n(intel_crtc, M1_N1);
-
-	intel_set_pipe_timings(intel_crtc);
-	intel_set_pipe_src_size(intel_crtc);
-
-	i9xx_set_pipeconf(intel_crtc);
-
-	intel_crtc->active = true;
-
-	if (!IS_GEN2(dev_priv))
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
-	intel_encoders_pre_enable(crtc, pipe_config, old_state);
-
-	i9xx_enable_pll(intel_crtc);
-
-	i9xx_pfit_enable(intel_crtc);
-
-	intel_color_load_luts(&pipe_config->base);
-
-	intel_update_watermarks(intel_crtc);
-	intel_enable_pipe(intel_crtc);
-
-	assert_vblank_disabled(crtc);
-	drm_crtc_vblank_on(crtc);
-
-	intel_encoders_enable(crtc, pipe_config, old_state);
-}
-
-static void i9xx_pfit_disable(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (!crtc->config->gmch_pfit.control)
-		return;
-
-	assert_pipe_disabled(dev_priv, crtc->pipe);
-
-	DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
-			 I915_READ(PFIT_CONTROL));
-	I915_WRITE(PFIT_CONTROL, 0);
-}
-
-static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
-			      struct drm_atomic_state *old_state)
-{
-	struct drm_crtc *crtc = old_crtc_state->base.crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-
-	/*
-	 * On gen2 planes are double buffered but the pipe isn't, so we must
-	 * wait for planes to fully turn off before disabling the pipe.
-	 */
-	if (IS_GEN2(dev_priv))
-		intel_wait_for_vblank(dev_priv, pipe);
-
-	intel_encoders_disable(crtc, old_crtc_state, old_state);
-
-	drm_crtc_vblank_off(crtc);
-	assert_vblank_disabled(crtc);
-
-	intel_disable_pipe(intel_crtc);
-
-	i9xx_pfit_disable(intel_crtc);
-
-	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
-
-	if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
-		if (IS_CHERRYVIEW(dev_priv))
-			chv_disable_pll(dev_priv, pipe);
-		else if (IS_VALLEYVIEW(dev_priv))
-			vlv_disable_pll(dev_priv, pipe);
-		else
-			i9xx_disable_pll(intel_crtc);
-	}
-
-	intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
-
-	if (!IS_GEN2(dev_priv))
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-}
-
-static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
-{
-	struct intel_encoder *encoder;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-	enum intel_display_power_domain domain;
-	unsigned long domains;
-	struct drm_atomic_state *state;
-	struct intel_crtc_state *crtc_state;
-	int ret;
-
-	if (!intel_crtc->active)
-		return;
-
-	if (to_intel_plane_state(crtc->primary->state)->base.visible) {
-		WARN_ON(intel_crtc->flip_work);
-
-		intel_pre_disable_primary_noatomic(crtc);
-
-		intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
-		to_intel_plane_state(crtc->primary->state)->base.visible = false;
-	}
-
-	state = drm_atomic_state_alloc(crtc->dev);
-	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
-
-	/* Everything's already locked, -EDEADLK can't happen. */
-	crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
-	ret = drm_atomic_add_affected_connectors(state, crtc);
-
-	WARN_ON(IS_ERR(crtc_state) || ret);
-
-	dev_priv->display.crtc_disable(crtc_state, state);
-
-	drm_atomic_state_put(state);
-
-	DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
-		      crtc->base.id, crtc->name);
+	DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
+		      crtc->base.id, crtc->name);
 
 	WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0);
 	crtc->state->active = false;
@@ -7124,543 +6182,121 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
 		goto retry;
 	}
 
-	if (needs_recompute)
-		return RETRY;
-
-	return ret;
-}
-
-static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
-				     struct intel_crtc_state *pipe_config)
-{
-	if (pipe_config->pipe_bpp > 24)
-		return false;
-
-	/* HSW can handle pixel rate up to cdclk? */
-	if (IS_HASWELL(dev_priv))
-		return true;
-
-	/*
-	 * We compare against max which means we must take
-	 * the increased cdclk requirement into account when
-	 * calculating the new cdclk.
-	 *
-	 * Should measure whether using a lower cdclk w/o IPS
-	 */
-	return pipe_config->pixel_rate <=
-		dev_priv->max_cdclk_freq * 95 / 100;
-}
-
-static void hsw_compute_ips_config(struct intel_crtc *crtc,
-				   struct intel_crtc_state *pipe_config)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	pipe_config->ips_enabled = i915.enable_ips &&
-		hsw_crtc_supports_ips(crtc) &&
-		pipe_config_supports_ips(dev_priv, pipe_config);
-}
-
-static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
-{
-	const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
-	/* GDG double wide on either pipe, otherwise pipe A only */
-	return INTEL_INFO(dev_priv)->gen < 4 &&
-		(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
-}
-
-static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
-
-	if (HAS_GMCH_DISPLAY(dev_priv))
-		/* FIXME calculate proper pipe pixel rate GMCH pfit */
-		crtc_state->pixel_rate =
-			crtc_state->base.adjusted_mode.crtc_clock;
-	else
-		crtc_state->pixel_rate =
-			ilk_pipe_pixel_rate(crtc_state);
-}
-
-static int intel_crtc_compute_config(struct intel_crtc *crtc,
-				     struct intel_crtc_state *pipe_config)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
-	int clock_limit = dev_priv->max_dotclk_freq;
-
-	if (INTEL_GEN(dev_priv) < 4) {
-		clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
-
-		/*
-		 * Enable double wide mode when the dot clock
-		 * is > 90% of the (display) core speed.
-		 */
-		if (intel_crtc_supports_double_wide(crtc) &&
-		    adjusted_mode->crtc_clock > clock_limit) {
-			clock_limit = dev_priv->max_dotclk_freq;
-			pipe_config->double_wide = true;
-		}
-	}
-
-	if (adjusted_mode->crtc_clock > clock_limit) {
-		DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
-			      adjusted_mode->crtc_clock, clock_limit,
-			      yesno(pipe_config->double_wide));
-		return -EINVAL;
-	}
-
-	/*
-	 * Pipe horizontal size must be even in:
-	 * - DVO ganged mode
-	 * - LVDS dual channel mode
-	 * - Double wide pipe
-	 */
-	if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
-	     intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
-		pipe_config->pipe_src_w &= ~1;
-
-	/* Cantiga+ cannot handle modes with a hsync front porch of 0.
-	 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
-	 */
-	if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
-		adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
-		return -EINVAL;
-
-	intel_crtc_compute_pixel_rate(pipe_config);
-
-	if (HAS_IPS(dev_priv))
-		hsw_compute_ips_config(crtc, pipe_config);
-
-	if (pipe_config->has_pch_encoder)
-		return ironlake_fdi_compute_config(crtc, pipe_config);
-
-	return 0;
-}
-
-static int skylake_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	u32 cdctl;
-
-	skl_dpll0_update(dev_priv);
-
-	if (dev_priv->cdclk_pll.vco == 0)
-		return dev_priv->cdclk_pll.ref;
-
-	cdctl = I915_READ(CDCLK_CTL);
-
-	if (dev_priv->cdclk_pll.vco == 8640000) {
-		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
-		case CDCLK_FREQ_450_432:
-			return 432000;
-		case CDCLK_FREQ_337_308:
-			return 308571;
-		case CDCLK_FREQ_540:
-			return 540000;
-		case CDCLK_FREQ_675_617:
-			return 617143;
-		default:
-			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
-		}
-	} else {
-		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
-		case CDCLK_FREQ_450_432:
-			return 450000;
-		case CDCLK_FREQ_337_308:
-			return 337500;
-		case CDCLK_FREQ_540:
-			return 540000;
-		case CDCLK_FREQ_675_617:
-			return 675000;
-		default:
-			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
-		}
-	}
-
-	return dev_priv->cdclk_pll.ref;
-}
-
-static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
-{
-	u32 val;
-
-	dev_priv->cdclk_pll.ref = 19200;
-	dev_priv->cdclk_pll.vco = 0;
-
-	val = I915_READ(BXT_DE_PLL_ENABLE);
-	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
-		return;
-
-	if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
-		return;
-
-	val = I915_READ(BXT_DE_PLL_CTL);
-	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
-		dev_priv->cdclk_pll.ref;
-}
-
-static int broxton_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	u32 divider;
-	int div, vco;
-
-	bxt_de_pll_update(dev_priv);
-
-	vco = dev_priv->cdclk_pll.vco;
-	if (vco == 0)
-		return dev_priv->cdclk_pll.ref;
-
-	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
-
-	switch (divider) {
-	case BXT_CDCLK_CD2X_DIV_SEL_1:
-		div = 2;
-		break;
-	case BXT_CDCLK_CD2X_DIV_SEL_1_5:
-		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
-		div = 3;
-		break;
-	case BXT_CDCLK_CD2X_DIV_SEL_2:
-		div = 4;
-		break;
-	case BXT_CDCLK_CD2X_DIV_SEL_4:
-		div = 8;
-		break;
-	default:
-		MISSING_CASE(divider);
-		return dev_priv->cdclk_pll.ref;
-	}
-
-	return DIV_ROUND_CLOSEST(vco, div);
-}
-
-static int broadwell_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	uint32_t lcpll = I915_READ(LCPLL_CTL);
-	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
-
-	if (lcpll & LCPLL_CD_SOURCE_FCLK)
-		return 800000;
-	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
-		return 450000;
-	else if (freq == LCPLL_CLK_FREQ_450)
-		return 450000;
-	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
-		return 540000;
-	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
-		return 337500;
-	else
-		return 675000;
-}
-
-static int haswell_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	uint32_t lcpll = I915_READ(LCPLL_CTL);
-	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
-
-	if (lcpll & LCPLL_CD_SOURCE_FCLK)
-		return 800000;
-	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
-		return 450000;
-	else if (freq == LCPLL_CLK_FREQ_450)
-		return 450000;
-	else if (IS_HSW_ULT(dev_priv))
-		return 337500;
-	else
-		return 540000;
-}
-
-static int valleyview_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
-				      CCK_DISPLAY_CLOCK_CONTROL);
-}
-
-static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	return 450000;
-}
-
-static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	return 400000;
-}
-
-static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	return 333333;
-}
-
-static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	return 200000;
-}
-
-static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	struct pci_dev *pdev = dev_priv->drm.pdev;
-	u16 gcfgc = 0;
-
-	pci_read_config_word(pdev, GCFGC, &gcfgc);
-
-	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
-	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
-		return 266667;
-	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
-		return 333333;
-	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
-		return 444444;
-	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
-		return 200000;
-	default:
-		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
-	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
-		return 133333;
-	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
-		return 166667;
-	}
-}
-
-static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	struct pci_dev *pdev = dev_priv->drm.pdev;
-	u16 gcfgc = 0;
-
-	pci_read_config_word(pdev, GCFGC, &gcfgc);
-
-	if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
-		return 133333;
-	else {
-		switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
-		case GC_DISPLAY_CLOCK_333_MHZ:
-			return 333333;
-		default:
-		case GC_DISPLAY_CLOCK_190_200_MHZ:
-			return 190000;
-		}
-	}
-}
-
-static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	return 266667;
+	if (needs_recompute)
+		return RETRY;
+
+	return ret;
 }
 
-static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
+static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
+				     struct intel_crtc_state *pipe_config)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
-	u16 hpllcc = 0;
-
-	/*
-	 * 852GM/852GMV only supports 133 MHz and the HPLLCC
-	 * encoding is different :(
-	 * FIXME is this the right way to detect 852GM/852GMV?
-	 */
-	if (pdev->revision == 0x1)
-		return 133333;
+	if (pipe_config->pipe_bpp > 24)
+		return false;
 
-	pci_bus_read_config_word(pdev->bus,
-				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
+	/* HSW can handle pixel rate up to cdclk? */
+	if (IS_HASWELL(dev_priv))
+		return true;
 
-	/* Assume that the hardware is in the high speed state.  This
-	 * should be the default.
+	/*
+	 * We compare against max which means we must take
+	 * the increased cdclk requirement into account when
+	 * calculating the new cdclk.
+	 *
+	 * Should measure whether using a lower cdclk w/o IPS
 	 */
-	switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
-	case GC_CLOCK_133_200:
-	case GC_CLOCK_133_200_2:
-	case GC_CLOCK_100_200:
-		return 200000;
-	case GC_CLOCK_166_250:
-		return 250000;
-	case GC_CLOCK_100_133:
-		return 133333;
-	case GC_CLOCK_133_266:
-	case GC_CLOCK_133_266_2:
-	case GC_CLOCK_166_266:
-		return 266667;
-	}
-
-	/* Shouldn't happen */
-	return 0;
+	return pipe_config->pixel_rate <=
+		dev_priv->max_cdclk_freq * 95 / 100;
 }
 
-static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
+static void hsw_compute_ips_config(struct intel_crtc *crtc,
+				   struct intel_crtc_state *pipe_config)
 {
-	return 133333;
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	pipe_config->ips_enabled = i915.enable_ips &&
+		hsw_crtc_supports_ips(crtc) &&
+		pipe_config_supports_ips(dev_priv, pipe_config);
 }
 
-static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
+static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
 {
-	static const unsigned int blb_vco[8] = {
-		[0] = 3200000,
-		[1] = 4000000,
-		[2] = 5333333,
-		[3] = 4800000,
-		[4] = 6400000,
-	};
-	static const unsigned int pnv_vco[8] = {
-		[0] = 3200000,
-		[1] = 4000000,
-		[2] = 5333333,
-		[3] = 4800000,
-		[4] = 2666667,
-	};
-	static const unsigned int cl_vco[8] = {
-		[0] = 3200000,
-		[1] = 4000000,
-		[2] = 5333333,
-		[3] = 6400000,
-		[4] = 3333333,
-		[5] = 3566667,
-		[6] = 4266667,
-	};
-	static const unsigned int elk_vco[8] = {
-		[0] = 3200000,
-		[1] = 4000000,
-		[2] = 5333333,
-		[3] = 4800000,
-	};
-	static const unsigned int ctg_vco[8] = {
-		[0] = 3200000,
-		[1] = 4000000,
-		[2] = 5333333,
-		[3] = 6400000,
-		[4] = 2666667,
-		[5] = 4266667,
-	};
-	const unsigned int *vco_table;
-	unsigned int vco;
-	uint8_t tmp = 0;
-
-	/* FIXME other chipsets? */
-	if (IS_GM45(dev_priv))
-		vco_table = ctg_vco;
-	else if (IS_G4X(dev_priv))
-		vco_table = elk_vco;
-	else if (IS_I965GM(dev_priv))
-		vco_table = cl_vco;
-	else if (IS_PINEVIEW(dev_priv))
-		vco_table = pnv_vco;
-	else if (IS_G33(dev_priv))
-		vco_table = blb_vco;
-	else
-		return 0;
-
-	tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
-
-	vco = vco_table[tmp & 0x7];
-	if (vco == 0)
-		DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
-	else
-		DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
+	const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-	return vco;
+	/* GDG double wide on either pipe, otherwise pipe A only */
+	return INTEL_INFO(dev_priv)->gen < 4 &&
+		(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
 }
 
-static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
+static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
-	uint16_t tmp = 0;
-
-	pci_read_config_word(pdev, GCFGC, &tmp);
-
-	cdclk_sel = (tmp >> 12) & 0x1;
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
 
-	switch (vco) {
-	case 2666667:
-	case 4000000:
-	case 5333333:
-		return cdclk_sel ? 333333 : 222222;
-	case 3200000:
-		return cdclk_sel ? 320000 : 228571;
-	default:
-		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n", vco, tmp);
-		return 222222;
-	}
+	if (HAS_GMCH_DISPLAY(dev_priv))
+		/* FIXME calculate proper pipe pixel rate GMCH pfit */
+		crtc_state->pixel_rate =
+			crtc_state->base.adjusted_mode.crtc_clock;
+	else
+		crtc_state->pixel_rate =
+			ilk_pipe_pixel_rate(crtc_state);
 }
 
-static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
+static int intel_crtc_compute_config(struct intel_crtc *crtc,
+				     struct intel_crtc_state *pipe_config)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
-	static const uint8_t div_3200[] = { 16, 10,  8 };
-	static const uint8_t div_4000[] = { 20, 12, 10 };
-	static const uint8_t div_5333[] = { 24, 16, 14 };
-	const uint8_t *div_table;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
-	uint16_t tmp = 0;
-
-	pci_read_config_word(pdev, GCFGC, &tmp);
-
-	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+	int clock_limit = dev_priv->max_dotclk_freq;
 
-	if (cdclk_sel >= ARRAY_SIZE(div_3200))
-		goto fail;
+	if (INTEL_GEN(dev_priv) < 4) {
+		clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
 
-	switch (vco) {
-	case 3200000:
-		div_table = div_3200;
-		break;
-	case 4000000:
-		div_table = div_4000;
-		break;
-	case 5333333:
-		div_table = div_5333;
-		break;
-	default:
-		goto fail;
+		/*
+		 * Enable double wide mode when the dot clock
+		 * is > 90% of the (display) core speed.
+		 */
+		if (intel_crtc_supports_double_wide(crtc) &&
+		    adjusted_mode->crtc_clock > clock_limit) {
+			clock_limit = dev_priv->max_dotclk_freq;
+			pipe_config->double_wide = true;
+		}
 	}
 
-	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
-
-fail:
-	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n", vco, tmp);
-	return 200000;
-}
-
-static int g33_get_cdclk(struct drm_i915_private *dev_priv)
-{
-	struct pci_dev *pdev = dev_priv->drm.pdev;
-	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
-	static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
-	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
-	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
-	const uint8_t *div_table;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
-	uint16_t tmp = 0;
+	if (adjusted_mode->crtc_clock > clock_limit) {
+		DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+			      adjusted_mode->crtc_clock, clock_limit,
+			      yesno(pipe_config->double_wide));
+		return -EINVAL;
+	}
 
-	pci_read_config_word(pdev, GCFGC, &tmp);
+	/*
+	 * Pipe horizontal size must be even in:
+	 * - DVO ganged mode
+	 * - LVDS dual channel mode
+	 * - Double wide pipe
+	 */
+	if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
+	     intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
+		pipe_config->pipe_src_w &= ~1;
 
-	cdclk_sel = (tmp >> 4) & 0x7;
+	/* Cantiga+ cannot handle modes with a hsync front porch of 0.
+	 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
+	 */
+	if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
+		adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
+		return -EINVAL;
 
-	if (cdclk_sel >= ARRAY_SIZE(div_3200))
-		goto fail;
+	intel_crtc_compute_pixel_rate(pipe_config);
 
-	switch (vco) {
-	case 3200000:
-		div_table = div_3200;
-		break;
-	case 4000000:
-		div_table = div_4000;
-		break;
-	case 4800000:
-		div_table = div_4800;
-		break;
-	case 5333333:
-		div_table = div_5333;
-		break;
-	default:
-		goto fail;
-	}
+	if (HAS_IPS(dev_priv))
+		hsw_compute_ips_config(crtc, pipe_config);
 
-	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
+	if (pipe_config->has_pch_encoder)
+		return ironlake_fdi_compute_config(crtc, pipe_config);
 
-fail:
-	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n", vco, tmp);
-	return 190476;
+	return 0;
 }
 
 static void
@@ -10225,245 +8861,6 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 	}
 }
 
-static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_device *dev = old_state->dev;
-	struct intel_atomic_state *old_intel_state =
-		to_intel_atomic_state(old_state);
-	unsigned int req_cdclk = old_intel_state->dev_cdclk;
-
-	bxt_set_cdclk(to_i915(dev), req_cdclk);
-}
-
-static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
-					  int pixel_rate)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
-
-	/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
-	if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
-		pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
-
-	/* BSpec says "Do not use DisplayPort with CDCLK less than
-	 * 432 MHz, audio enabled, port width x4, and link rate
-	 * HBR2 (5.4 GHz), or else there may be audio corruption or
-	 * screen corruption."
-	 */
-	if (intel_crtc_has_dp_encoder(crtc_state) &&
-	    crtc_state->has_audio &&
-	    crtc_state->port_clock >= 540000 &&
-	    crtc_state->lane_count == 4)
-		pixel_rate = max(432000, pixel_rate);
-
-	return pixel_rate;
-}
-
-/* compute the max rate for new configuration */
-static int intel_max_pixel_rate(struct drm_atomic_state *state)
-{
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *cstate;
-	struct intel_crtc_state *crtc_state;
-	unsigned max_pixel_rate = 0, i;
-	enum pipe pipe;
-
-	memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
-	       sizeof(intel_state->min_pixclk));
-
-	for_each_crtc_in_state(state, crtc, cstate, i) {
-		int pixel_rate;
-
-		crtc_state = to_intel_crtc_state(cstate);
-		if (!crtc_state->base.enable) {
-			intel_state->min_pixclk[i] = 0;
-			continue;
-		}
-
-		pixel_rate = crtc_state->pixel_rate;
-
-		if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
-			pixel_rate = bdw_adjust_min_pipe_pixel_rate(crtc_state,
-								    pixel_rate);
-
-		intel_state->min_pixclk[i] = pixel_rate;
-	}
-
-	for_each_pipe(dev_priv, pipe)
-		max_pixel_rate = max(intel_state->min_pixclk[pipe], max_pixel_rate);
-
-	return max_pixel_rate;
-}
-
-static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
-{
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	uint32_t val, data;
-	int ret;
-
-	if (WARN((I915_READ(LCPLL_CTL) &
-		  (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
-		   LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
-		   LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
-		   LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
-		 "trying to change cdclk frequency with cdclk not enabled\n"))
-		return;
-
-	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = sandybridge_pcode_write(dev_priv,
-				      BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
-	mutex_unlock(&dev_priv->rps.hw_lock);
-	if (ret) {
-		DRM_ERROR("failed to inform pcode about cdclk change\n");
-		return;
-	}
-
-	val = I915_READ(LCPLL_CTL);
-	val |= LCPLL_CD_SOURCE_FCLK;
-	I915_WRITE(LCPLL_CTL, val);
-
-	if (wait_for_us(I915_READ(LCPLL_CTL) &
-			LCPLL_CD_SOURCE_FCLK_DONE, 1))
-		DRM_ERROR("Switching to FCLK failed\n");
-
-	val = I915_READ(LCPLL_CTL);
-	val &= ~LCPLL_CLK_FREQ_MASK;
-
-	switch (cdclk) {
-	case 450000:
-		val |= LCPLL_CLK_FREQ_450;
-		data = 0;
-		break;
-	case 540000:
-		val |= LCPLL_CLK_FREQ_54O_BDW;
-		data = 1;
-		break;
-	case 337500:
-		val |= LCPLL_CLK_FREQ_337_5_BDW;
-		data = 2;
-		break;
-	case 675000:
-		val |= LCPLL_CLK_FREQ_675_BDW;
-		data = 3;
-		break;
-	default:
-		WARN(1, "invalid cdclk frequency\n");
-		return;
-	}
-
-	I915_WRITE(LCPLL_CTL, val);
-
-	val = I915_READ(LCPLL_CTL);
-	val &= ~LCPLL_CD_SOURCE_FCLK;
-	I915_WRITE(LCPLL_CTL, val);
-
-	if (wait_for_us((I915_READ(LCPLL_CTL) &
-			LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
-		DRM_ERROR("Switching back to LCPLL failed\n");
-
-	mutex_lock(&dev_priv->rps.hw_lock);
-	sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
-	mutex_unlock(&dev_priv->rps.hw_lock);
-
-	I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
-
-	intel_update_cdclk(dev_priv);
-
-	WARN(cdclk != dev_priv->cdclk_freq,
-	     "cdclk requested %d kHz but got %d kHz\n",
-	     cdclk, dev_priv->cdclk_freq);
-}
-
-static int broadwell_calc_cdclk(int max_pixclk)
-{
-	if (max_pixclk > 540000)
-		return 675000;
-	else if (max_pixclk > 450000)
-		return 540000;
-	else if (max_pixclk > 337500)
-		return 450000;
-	else
-		return 337500;
-}
-
-static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
-{
-	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	int max_pixclk = intel_max_pixel_rate(state);
-	int cdclk;
-
-	/*
-	 * FIXME should also account for plane ratio
-	 * once 64bpp pixel formats are supported.
-	 */
-	cdclk = broadwell_calc_cdclk(max_pixclk);
-
-	if (cdclk > dev_priv->max_cdclk_freq) {
-		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
-			      cdclk, dev_priv->max_cdclk_freq);
-		return -EINVAL;
-	}
-
-	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
-	if (!intel_state->active_crtcs)
-		intel_state->dev_cdclk = broadwell_calc_cdclk(0);
-
-	return 0;
-}
-
-static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_device *dev = old_state->dev;
-	struct intel_atomic_state *old_intel_state =
-		to_intel_atomic_state(old_state);
-	unsigned req_cdclk = old_intel_state->dev_cdclk;
-
-	broadwell_set_cdclk(dev, req_cdclk);
-}
-
-static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
-{
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	const int max_pixclk = intel_max_pixel_rate(state);
-	int vco = intel_state->cdclk_pll_vco;
-	int cdclk;
-
-	/*
-	 * FIXME should also account for plane ratio
-	 * once 64bpp pixel formats are supported.
-	 */
-	cdclk = skl_calc_cdclk(max_pixclk, vco);
-
-	/*
-	 * FIXME move the cdclk caclulation to
-	 * compute_config() so we can fail gracegully.
-	 */
-	if (cdclk > dev_priv->max_cdclk_freq) {
-		DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
-			  cdclk, dev_priv->max_cdclk_freq);
-		cdclk = dev_priv->max_cdclk_freq;
-	}
-
-	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
-	if (!intel_state->active_crtcs)
-		intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
-
-	return 0;
-}
-
-static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(old_state);
-	unsigned int req_cdclk = intel_state->dev_cdclk;
-	unsigned int req_vco = intel_state->cdclk_pll_vco;
-
-	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
-}
-
 static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
 				      struct intel_crtc_state *crtc_state)
 {
@@ -16019,6 +14416,8 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
  */
 void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 {
+	intel_init_cdclk_hooks(dev_priv);
+
 	if (INTEL_INFO(dev_priv)->gen >= 9) {
 		dev_priv->display.get_pipe_config = haswell_get_pipe_config;
 		dev_priv->display.get_initial_plane_config =
@@ -16087,52 +14486,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 	}
 
-	/* Returns the core display clock speed */
-	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
-		dev_priv->display.get_cdclk = skylake_get_cdclk;
-	else if (IS_GEN9_LP(dev_priv))
-		dev_priv->display.get_cdclk = broxton_get_cdclk;
-	else if (IS_BROADWELL(dev_priv))
-		dev_priv->display.get_cdclk = broadwell_get_cdclk;
-	else if (IS_HASWELL(dev_priv))
-		dev_priv->display.get_cdclk = haswell_get_cdclk;
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		dev_priv->display.get_cdclk = valleyview_get_cdclk;
-	else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
-		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
-	else if (IS_GEN5(dev_priv))
-		dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
-	else if (IS_GM45(dev_priv))
-		dev_priv->display.get_cdclk = gm45_get_cdclk;
-	else if (IS_G4X(dev_priv))
-		dev_priv->display.get_cdclk = g33_get_cdclk;
-	else if (IS_I965GM(dev_priv))
-		dev_priv->display.get_cdclk = i965gm_get_cdclk;
-	else if (IS_I965G(dev_priv))
-		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
-	else if (IS_PINEVIEW(dev_priv))
-		dev_priv->display.get_cdclk = pnv_get_cdclk;
-	else if (IS_G33(dev_priv))
-		dev_priv->display.get_cdclk = g33_get_cdclk;
-	else if (IS_I945GM(dev_priv))
-		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
-	else if (IS_I945G(dev_priv))
-		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
-	else if (IS_I915GM(dev_priv))
-		dev_priv->display.get_cdclk = i915gm_get_cdclk;
-	else if (IS_I915G(dev_priv))
-		dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
-	else if (IS_I865G(dev_priv))
-		dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
-	else if (IS_I85X(dev_priv))
-		dev_priv->display.get_cdclk = i85x_get_cdclk;
-	else  if (IS_I845G(dev_priv))
-		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
-	else { /* 830 */
-		WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz CDCLK\n");
-		dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
-	}
-
 	if (IS_GEN5(dev_priv)) {
 		dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
 	} else if (IS_GEN6(dev_priv)) {
@@ -16144,28 +14497,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 		dev_priv->display.fdi_link_train = hsw_fdi_link_train;
 	}
 
-	if (IS_BROADWELL(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			broadwell_modeset_commit_cdclk;
-		dev_priv->display.modeset_calc_cdclk =
-			broadwell_modeset_calc_cdclk;
-	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			valleyview_modeset_commit_cdclk;
-		dev_priv->display.modeset_calc_cdclk =
-			valleyview_modeset_calc_cdclk;
-	} else if (IS_GEN9_LP(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			bxt_modeset_commit_cdclk;
-		dev_priv->display.modeset_calc_cdclk =
-			bxt_modeset_calc_cdclk;
-	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			skl_modeset_commit_cdclk;
-		dev_priv->display.modeset_calc_cdclk =
-			skl_modeset_calc_cdclk;
-	}
-
 	if (dev_priv->info.gen >= 9)
 		dev_priv->display.update_crtcs = skl_update_crtcs;
 	else
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3969e786d566..8d93b7bda3ff 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1220,12 +1220,19 @@ void intel_audio_codec_disable(struct intel_encoder *encoder);
 void i915_audio_component_init(struct drm_i915_private *dev_priv);
 void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
+/* intel_cdclk.c */
+void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
+void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
+void intel_update_cdclk(struct drm_i915_private *dev_priv);
+void intel_update_rawclk(struct drm_i915_private *dev_priv);
+
 /* intel_display.c */
 enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
-void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco);
 void intel_update_rawclk(struct drm_i915_private *dev_priv);
 int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
 		      const char *name, u32 reg, int ref_freq);
+int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
+			   const char *name, u32 reg);
 void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv);
 void lpt_disable_iclkip(struct drm_i915_private *dev_priv);
 extern const struct drm_plane_funcs intel_plane_funcs;
-- 
2.10.2

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

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

* [PATCH 06/14] drm/i915: Pass computed vco to bxt_set_cdclk()
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (4 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-22 13:22   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure ville.syrjala
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Rather than compute the vco inside bxt_set_cdclk() let's precompute it
outside and pass it in. A small step towards a fully precomputed cdclk
state.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_cdclk.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 1804c43553b7..89be610d0879 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -1080,15 +1080,11 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
 	dev_priv->cdclk_pll.vco = vco;
 }
 
-static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
+			  int cdclk, int vco)
 {
 	u32 val, divider;
-	int vco, ret;
-
-	if (IS_GEMINILAKE(dev_priv))
-		vco = glk_de_pll_vco(dev_priv, cdclk);
-	else
-		vco = bxt_de_pll_vco(dev_priv, cdclk);
+	int ret;
 
 	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
 			 cdclk, vco);
@@ -1212,7 +1208,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 
 void bxt_init_cdclk(struct drm_i915_private *dev_priv)
 {
-	int cdclk;
+	int cdclk, vco;
 
 	bxt_sanitize_cdclk(dev_priv);
 
@@ -1224,17 +1220,20 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
 	 * - The initial CDCLK needs to be read from VBT.
 	 *   Need to make this change after VBT has changes for BXT.
 	 */
-	if (IS_GEMINILAKE(dev_priv))
+	if (IS_GEMINILAKE(dev_priv)) {
 		cdclk = glk_calc_cdclk(0);
-	else
+		vco = glk_de_pll_vco(dev_priv, cdclk);
+	} else {
 		cdclk = bxt_calc_cdclk(0);
+		vco = bxt_de_pll_vco(dev_priv, cdclk);
+	}
 
-	bxt_set_cdclk(dev_priv, cdclk);
+	bxt_set_cdclk(dev_priv, cdclk, vco);
 }
 
 void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
+	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
 }
 
 static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
@@ -1454,12 +1453,18 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 
 static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
-	struct drm_device *dev = old_state->dev;
+	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
 	struct intel_atomic_state *old_intel_state =
 		to_intel_atomic_state(old_state);
 	unsigned int req_cdclk = old_intel_state->dev_cdclk;
+	unsigned int req_vco;
+
+	if (IS_GEMINILAKE(dev_priv))
+		req_vco = glk_de_pll_vco(dev_priv, req_cdclk);
+	else
+		req_vco = bxt_de_pll_vco(dev_priv, req_cdclk);
 
-	bxt_set_cdclk(to_i915(dev), req_cdclk);
+	bxt_set_cdclk(dev_priv, req_cdclk, req_vco);
 }
 
 static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
-- 
2.10.2

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

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

* [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (5 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH 06/14] drm/i915: Pass computed vco to bxt_set_cdclk() ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-22 14:14   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH v2 08/14] drm/i915: Track full cdclk state for the logical and actual cdclk frequencies ville.syrjala
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Introduce intel_cdclk state which for now will track the cdclk
frequency, the vco frequency and the reference frequency (not sure we
want the last one, but I put it there anyway). We'll also make the
.get_cdclk() function fill out this state structure rather than
just returning the current cdclk frequency.

One immediate benefit is that calling .get_cdclk() will no longer
clobber state stored under dev_priv unless ex[plicitly told to do
so. Previously it clobbered the vco and reference clocks stored
there on some platforms.

We'll expand the use of this structure to actually precomputing the
state and whatnot later.

v2: Constify intel_cdclk_state_compare()

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c     |   2 +-
 drivers/gpu/drm/i915/i915_drv.h         |  14 +-
 drivers/gpu/drm/i915/intel_audio.c      |   2 +-
 drivers/gpu/drm/i915/intel_cdclk.c      | 359 ++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_display.c    |  18 +-
 drivers/gpu/drm/i915/intel_dp.c         |   2 +-
 drivers/gpu/drm/i915/intel_drv.h        |   3 +
 drivers/gpu/drm/i915/intel_fbc.c        |   2 +-
 drivers/gpu/drm/i915/intel_panel.c      |   4 +-
 drivers/gpu/drm/i915/intel_runtime_pm.c |   5 +-
 10 files changed, 240 insertions(+), 171 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 15deb2bc568b..c0171eef8f96 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1235,7 +1235,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
 		seq_puts(m, "no P-state info available\n");
 	}
 
-	seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk_freq);
+	seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk.hw.cdclk);
 	seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
 	seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 393b34fb2d1a..a4f1231ff8ca 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -609,9 +609,11 @@ struct intel_initial_plane_config;
 struct intel_crtc;
 struct intel_limit;
 struct dpll;
+struct intel_cdclk_state;
 
 struct drm_i915_display_funcs {
-	int (*get_cdclk)(struct drm_i915_private *dev_priv);
+	void (*get_cdclk)(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state);
 	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
 	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
 	int (*compute_intermediate_wm)(struct drm_device *dev,
@@ -2126,6 +2128,10 @@ struct i915_oa_ops {
 	bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv);
 };
 
+struct intel_cdclk_state {
+	unsigned int cdclk, vco, ref;
+};
+
 struct drm_i915_private {
 	struct drm_device drm;
 
@@ -2229,7 +2235,7 @@ struct drm_i915_private {
 
 	unsigned int fsb_freq, mem_freq, is_ddr3;
 	unsigned int skl_preferred_vco_freq;
-	unsigned int cdclk_freq, max_cdclk_freq;
+	unsigned int max_cdclk_freq;
 
 	/*
 	 * For reading holding any crtc lock is sufficient,
@@ -2243,8 +2249,8 @@ struct drm_i915_private {
 	unsigned int czclk_freq;
 
 	struct {
-		unsigned int vco, ref;
-	} cdclk_pll;
+		struct intel_cdclk_state hw;
+	} cdclk;
 
 	/**
 	 * wq - Driver workqueue for GEM.
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 3bbc96c1767f..a292246995ef 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -734,7 +734,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
 	if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
 		return -ENODEV;
 
-	return dev_priv->cdclk_freq;
+	return dev_priv->cdclk.hw.cdclk;
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 89be610d0879..13c3b5555473 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -23,37 +23,44 @@
 
 #include "intel_drv.h"
 
-static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
+static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv,
+				   struct intel_cdclk_state *cdclk_state)
 {
-	return 133333;
+	cdclk_state->cdclk = 133333;
 }
 
-static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
+static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv,
+				   struct intel_cdclk_state *cdclk_state)
 {
-	return 200000;
+	cdclk_state->cdclk = 200000;
 }
 
-static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
+static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv,
+				   struct intel_cdclk_state *cdclk_state)
 {
-	return 266667;
+	cdclk_state->cdclk = 266667;
 }
 
-static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
+static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv,
+				   struct intel_cdclk_state *cdclk_state)
 {
-	return 333333;
+	cdclk_state->cdclk = 333333;
 }
 
-static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
+static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv,
+				   struct intel_cdclk_state *cdclk_state)
 {
-	return 400000;
+	cdclk_state->cdclk = 400000;
 }
 
-static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
+static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
+				   struct intel_cdclk_state *cdclk_state)
 {
-	return 450000;
+	cdclk_state->cdclk = 450000;
 }
 
-static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
+static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
+			   struct intel_cdclk_state *cdclk_state)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 hpllcc = 0;
@@ -63,8 +70,10 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
 	 * encoding is different :(
 	 * FIXME is this the right way to detect 852GM/852GMV?
 	 */
-	if (pdev->revision == 0x1)
-		return 133333;
+	if (pdev->revision == 0x1) {
+		cdclk_state->cdclk = 133333;
+		return;
+	}
 
 	pci_bus_read_config_word(pdev->bus,
 				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
@@ -76,37 +85,43 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
 	case GC_CLOCK_133_200:
 	case GC_CLOCK_133_200_2:
 	case GC_CLOCK_100_200:
-		return 200000;
+		cdclk_state->cdclk = 200000;
+		break;
 	case GC_CLOCK_166_250:
-		return 250000;
+		cdclk_state->cdclk = 250000;
+		break;
 	case GC_CLOCK_100_133:
-		return 133333;
+		cdclk_state->cdclk = 133333;
+		break;
 	case GC_CLOCK_133_266:
 	case GC_CLOCK_133_266_2:
 	case GC_CLOCK_166_266:
-		return 266667;
+		cdclk_state->cdclk = 266667;
+		break;
 	}
-
-	/* Shouldn't happen */
-	return 0;
 }
 
-static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
+static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
+			     struct intel_cdclk_state *cdclk_state)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 gcfgc = 0;
 
 	pci_read_config_word(pdev, GCFGC, &gcfgc);
 
-	if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
-		return 133333;
+	if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
+		cdclk_state->cdclk = 133333;
+		return;
+	}
 
 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
 	case GC_DISPLAY_CLOCK_333_MHZ:
-		return 333333;
+		cdclk_state->cdclk = 333333;
+		break;
 	default:
 	case GC_DISPLAY_CLOCK_190_200_MHZ:
-		return 190000;
+		cdclk_state->cdclk = 190000;
+		break;
 	}
 }
 
@@ -178,7 +193,8 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
 	return vco;
 }
 
-static int g33_get_cdclk(struct drm_i915_private *dev_priv)
+static void g33_get_cdclk(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
@@ -186,9 +202,11 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
 	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
 	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
 	const uint8_t *div_table;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+	unsigned int cdclk_sel;
 	uint16_t tmp = 0;
 
+	cdclk_state->vco = intel_hpll_vco(dev_priv);
+
 	pci_read_config_word(pdev, GCFGC, &tmp);
 
 	cdclk_sel = (tmp >> 4) & 0x7;
@@ -196,7 +214,7 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
 	if (cdclk_sel >= ARRAY_SIZE(div_3200))
 		goto fail;
 
-	switch (vco) {
+	switch (cdclk_state->vco) {
 	case 3200000:
 		div_table = div_3200;
 		break;
@@ -213,15 +231,18 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
 		goto fail;
 	}
 
-	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
+	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
+					       div_table[cdclk_sel]);
+	return;
 
 fail:
 	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
-		  vco, tmp);
-	return 190476;
+		  cdclk_state->vco, tmp);
+	cdclk_state->cdclk = 190476;
 }
 
-static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
+static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 gcfgc = 0;
@@ -230,32 +251,41 @@ static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
 
 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
 	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
-		return 266667;
+		cdclk_state->cdclk = 266667;
+		break;
 	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
-		return 333333;
+		cdclk_state->cdclk = 333333;
+		break;
 	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
-		return 444444;
+		cdclk_state->cdclk = 444444;
+		break;
 	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
-		return 200000;
+		cdclk_state->cdclk = 200000;
+		break;
 	default:
 		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
 	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
-		return 133333;
+		cdclk_state->cdclk = 133333;
+		break;
 	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
-		return 166667;
+		cdclk_state->cdclk = 166667;
+		break;
 	}
 }
 
-static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
+static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
+			     struct intel_cdclk_state *cdclk_state)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	static const uint8_t div_3200[] = { 16, 10,  8 };
 	static const uint8_t div_4000[] = { 20, 12, 10 };
 	static const uint8_t div_5333[] = { 24, 16, 14 };
 	const uint8_t *div_table;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+	unsigned int cdclk_sel;
 	uint16_t tmp = 0;
 
+	cdclk_state->vco = intel_hpll_vco(dev_priv);
+
 	pci_read_config_word(pdev, GCFGC, &tmp);
 
 	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
@@ -263,7 +293,7 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
 	if (cdclk_sel >= ARRAY_SIZE(div_3200))
 		goto fail;
 
-	switch (vco) {
+	switch (cdclk_state->vco) {
 	case 3200000:
 		div_table = div_3200;
 		break;
@@ -277,53 +307,62 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
 		goto fail;
 	}
 
-	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
+	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
+					       div_table[cdclk_sel]);
+	return;
 
 fail:
 	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
-		  vco, tmp);
-	return 200000;
+		  cdclk_state->vco, tmp);
+	cdclk_state->cdclk = 200000;
 }
 
-static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
+static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
+			   struct intel_cdclk_state *cdclk_state)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
+	unsigned int cdclk_sel;
 	uint16_t tmp = 0;
 
+	cdclk_state->vco = intel_hpll_vco(dev_priv);
+
 	pci_read_config_word(pdev, GCFGC, &tmp);
 
 	cdclk_sel = (tmp >> 12) & 0x1;
 
-	switch (vco) {
+	switch (cdclk_state->vco) {
 	case 2666667:
 	case 4000000:
 	case 5333333:
-		return cdclk_sel ? 333333 : 222222;
+		cdclk_state->cdclk = cdclk_sel ? 333333 : 222222;
+		break;
 	case 3200000:
-		return cdclk_sel ? 320000 : 228571;
+		cdclk_state->cdclk = cdclk_sel ? 320000 : 228571;
+		break;
 	default:
 		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
-			  vco, tmp);
-		return 222222;
+			  cdclk_state->vco, tmp);
+		cdclk_state->cdclk = 222222;
+		break;
 	}
 }
 
-static int hsw_get_cdclk(struct drm_i915_private *dev_priv)
+static void hsw_get_cdclk(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state)
 {
 	uint32_t lcpll = I915_READ(LCPLL_CTL);
 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
 
 	if (lcpll & LCPLL_CD_SOURCE_FCLK)
-		return 800000;
+		cdclk_state->cdclk = 800000;
 	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
-		return 450000;
+		cdclk_state->cdclk = 450000;
 	else if (freq == LCPLL_CLK_FREQ_450)
-		return 450000;
+		cdclk_state->cdclk = 450000;
 	else if (IS_HSW_ULT(dev_priv))
-		return 337500;
+		cdclk_state->cdclk = 337500;
 	else
-		return 540000;
+		cdclk_state->cdclk = 540000;
 }
 
 static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
@@ -349,10 +388,13 @@ static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
 		return 200000;
 }
 
-static int vlv_get_cdclk(struct drm_i915_private *dev_priv)
+static void vlv_get_cdclk(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state)
 {
-	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
-				      CCK_DISPLAY_CLOCK_CONTROL);
+	cdclk_state->vco = vlv_get_hpll_vco(dev_priv);
+	cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
+					       CCK_DISPLAY_CLOCK_CONTROL,
+					       cdclk_state->vco);
 }
 
 static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
@@ -364,7 +406,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
 	else
 		default_credits = PFI_CREDIT(8);
 
-	if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
+	if (dev_priv->cdclk.hw.cdclk >= dev_priv->czclk_freq) {
 		/* CHV suggested value is 31 or 63 */
 		if (IS_CHERRYVIEW(dev_priv))
 			credits = PFI_CREDIT_63;
@@ -396,8 +438,6 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
-	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
-
 	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
 		cmd = 2;
 	else if (cdclk == 266667)
@@ -461,8 +501,6 @@ static void chv_set_cdclk(struct drm_device *dev, int cdclk)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
-	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
-
 	switch (cdclk) {
 	case 333333:
 	case 320000:
@@ -508,23 +546,24 @@ static int bdw_calc_cdclk(int max_pixclk)
 		return 337500;
 }
 
-static int bdw_get_cdclk(struct drm_i915_private *dev_priv)
+static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state)
 {
 	uint32_t lcpll = I915_READ(LCPLL_CTL);
 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
 
 	if (lcpll & LCPLL_CD_SOURCE_FCLK)
-		return 800000;
+		cdclk_state->cdclk = 800000;
 	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
-		return 450000;
+		cdclk_state->cdclk = 450000;
 	else if (freq == LCPLL_CLK_FREQ_450)
-		return 450000;
+		cdclk_state->cdclk = 450000;
 	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
-		return 540000;
+		cdclk_state->cdclk = 540000;
 	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
-		return 337500;
+		cdclk_state->cdclk = 337500;
 	else
-		return 675000;
+		cdclk_state->cdclk = 675000;
 }
 
 static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
@@ -601,9 +640,9 @@ static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
 
 	intel_update_cdclk(dev_priv);
 
-	WARN(cdclk != dev_priv->cdclk_freq,
+	WARN(cdclk != dev_priv->cdclk.hw.cdclk,
 	     "cdclk requested %d kHz but got %d kHz\n",
-	     cdclk, dev_priv->cdclk_freq);
+	     cdclk, dev_priv->cdclk.hw.cdclk);
 }
 
 static int skl_calc_cdclk(int max_pixclk, int vco)
@@ -629,12 +668,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco)
 	}
 }
 
-static void skl_dpll0_update(struct drm_i915_private *dev_priv)
+static void skl_dpll0_update(struct drm_i915_private *dev_priv,
+			     struct intel_cdclk_state *cdclk_state)
 {
 	u32 val;
 
-	dev_priv->cdclk_pll.ref = 24000;
-	dev_priv->cdclk_pll.vco = 0;
+	cdclk_state->ref = 24000;
+	cdclk_state->vco = 0;
 
 	val = I915_READ(LCPLL1_CTL);
 	if ((val & LCPLL_PLL_ENABLE) == 0)
@@ -656,11 +696,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
-		dev_priv->cdclk_pll.vco = 8100000;
+		cdclk_state->vco = 8100000;
 		break;
 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
-		dev_priv->cdclk_pll.vco = 8640000;
+		cdclk_state->vco = 8640000;
 		break;
 	default:
 		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
@@ -668,46 +708,57 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
 	}
 }
 
-static int skl_get_cdclk(struct drm_i915_private *dev_priv)
+static void skl_get_cdclk(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state)
 {
 	u32 cdctl;
 
-	skl_dpll0_update(dev_priv);
+	skl_dpll0_update(dev_priv, cdclk_state);
+
+	cdclk_state->cdclk = cdclk_state->ref;
 
-	if (dev_priv->cdclk_pll.vco == 0)
-		return dev_priv->cdclk_pll.ref;
+	if (cdclk_state->vco == 0)
+		return;
 
 	cdctl = I915_READ(CDCLK_CTL);
 
-	if (dev_priv->cdclk_pll.vco == 8640000) {
+	if (cdclk_state->vco == 8640000) {
 		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
 		case CDCLK_FREQ_450_432:
-			return 432000;
+			cdclk_state->cdclk = 432000;
+			break;
 		case CDCLK_FREQ_337_308:
-			return 308571;
+			cdclk_state->cdclk = 308571;
+			break;
 		case CDCLK_FREQ_540:
-			return 540000;
+			cdclk_state->cdclk = 540000;
+			break;
 		case CDCLK_FREQ_675_617:
-			return 617143;
+			cdclk_state->cdclk = 617143;
+			break;
 		default:
 			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
+			break;
 		}
 	} else {
 		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
 		case CDCLK_FREQ_450_432:
-			return 450000;
+			cdclk_state->cdclk = 450000;
+			break;
 		case CDCLK_FREQ_337_308:
-			return 337500;
+			cdclk_state->cdclk = 337500;
+			break;
 		case CDCLK_FREQ_540:
-			return 540000;
+			cdclk_state->cdclk = 540000;
+			break;
 		case CDCLK_FREQ_675_617:
-			return 675000;
+			cdclk_state->cdclk = 675000;
+			break;
 		default:
 			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
+			break;
 		}
 	}
-
-	return dev_priv->cdclk_pll.ref;
 }
 
 /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
@@ -770,7 +821,7 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
 				    5))
 		DRM_ERROR("DPLL0 not locked\n");
 
-	dev_priv->cdclk_pll.vco = vco;
+	dev_priv->cdclk.hw.vco = vco;
 
 	/* We'll want to keep using the current vco from now on. */
 	skl_set_preferred_cdclk_vco(dev_priv, vco);
@@ -784,7 +835,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
 				   1))
 		DRM_ERROR("Couldn't disable DPLL0\n");
 
-	dev_priv->cdclk_pll.vco = 0;
+	dev_priv->cdclk.hw.vco = 0;
 }
 
 static void skl_set_cdclk(struct drm_i915_private *dev_priv,
@@ -834,11 +885,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
 		break;
 	}
 
-	if (dev_priv->cdclk_pll.vco != 0 &&
-	    dev_priv->cdclk_pll.vco != vco)
+	if (dev_priv->cdclk.hw.vco != 0 &&
+	    dev_priv->cdclk.hw.vco != vco)
 		skl_dpll0_disable(dev_priv);
 
-	if (dev_priv->cdclk_pll.vco != vco)
+	if (dev_priv->cdclk.hw.vco != vco)
 		skl_dpll0_enable(dev_priv, vco);
 
 	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
@@ -866,8 +917,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 
 	intel_update_cdclk(dev_priv);
 	/* Is PLL enabled and locked ? */
-	if (dev_priv->cdclk_pll.vco == 0 ||
-	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
+	if (dev_priv->cdclk.hw.vco == 0 ||
+	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
 		goto sanitize;
 
 	/* DPLL okay; verify the cdclock
@@ -878,7 +929,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 	 */
 	cdctl = I915_READ(CDCLK_CTL);
 	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
-		skl_cdclk_decimal(dev_priv->cdclk_freq);
+		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
 	if (cdctl == expected)
 		/* All well; nothing to sanitize */
 		return;
@@ -887,14 +938,14 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
 
 	/* force cdclk programming */
-	dev_priv->cdclk_freq = 0;
+	dev_priv->cdclk.hw.cdclk = 0;
 	/* force full PLL disable + enable */
-	dev_priv->cdclk_pll.vco = -1;
+	dev_priv->cdclk.hw.vco = -1;
 }
 
 void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
+	skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
 }
 
 void skl_init_cdclk(struct drm_i915_private *dev_priv)
@@ -903,14 +954,15 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
 
 	skl_sanitize_cdclk(dev_priv);
 
-	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
+	if (dev_priv->cdclk.hw.cdclk != 0 &&
+	    dev_priv->cdclk.hw.vco != 0) {
 		/*
 		 * Use the current vco as our initial
 		 * guess as to what the preferred vco is.
 		 */
 		if (dev_priv->skl_preferred_vco_freq == 0)
 			skl_set_preferred_cdclk_vco(dev_priv,
-						    dev_priv->cdclk_pll.vco);
+						    dev_priv->cdclk.hw.vco);
 		return;
 	}
 
@@ -950,7 +1002,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
 	int ratio;
 
-	if (cdclk == dev_priv->cdclk_pll.ref)
+	if (cdclk == dev_priv->cdclk.hw.ref)
 		return 0;
 
 	switch (cdclk) {
@@ -967,14 +1019,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 		break;
 	}
 
-	return dev_priv->cdclk_pll.ref * ratio;
+	return dev_priv->cdclk.hw.ref * ratio;
 }
 
 static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
 	int ratio;
 
-	if (cdclk == dev_priv->cdclk_pll.ref)
+	if (cdclk == dev_priv->cdclk.hw.ref)
 		return 0;
 
 	switch (cdclk) {
@@ -987,15 +1039,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 		break;
 	}
 
-	return dev_priv->cdclk_pll.ref * ratio;
+	return dev_priv->cdclk.hw.ref * ratio;
 }
 
-static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
+static void bxt_de_pll_update(struct drm_i915_private *dev_priv,
+			      struct intel_cdclk_state *cdclk_state)
 {
 	u32 val;
 
-	dev_priv->cdclk_pll.ref = 19200;
-	dev_priv->cdclk_pll.vco = 0;
+	cdclk_state->ref = 19200;
+	cdclk_state->vco = 0;
 
 	val = I915_READ(BXT_DE_PLL_ENABLE);
 	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
@@ -1005,20 +1058,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
 		return;
 
 	val = I915_READ(BXT_DE_PLL_CTL);
-	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
-		dev_priv->cdclk_pll.ref;
+	cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
 }
 
-static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
+static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
+			  struct intel_cdclk_state *cdclk_state)
 {
 	u32 divider;
-	int div, vco;
+	int div;
 
-	bxt_de_pll_update(dev_priv);
+	bxt_de_pll_update(dev_priv, cdclk_state);
 
-	vco = dev_priv->cdclk_pll.vco;
-	if (vco == 0)
-		return dev_priv->cdclk_pll.ref;
+	cdclk_state->cdclk = cdclk_state->ref;
+
+	if (cdclk_state->vco == 0)
+		return;
 
 	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
 
@@ -1038,10 +1092,10 @@ static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
 		break;
 	default:
 		MISSING_CASE(divider);
-		return dev_priv->cdclk_pll.ref;
+		return;
 	}
 
-	return DIV_ROUND_CLOSEST(vco, div);
+	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
 }
 
 static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
@@ -1054,12 +1108,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
 				    1))
 		DRM_ERROR("timeout waiting for DE PLL unlock\n");
 
-	dev_priv->cdclk_pll.vco = 0;
+	dev_priv->cdclk.hw.vco = 0;
 }
 
 static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
 {
-	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
+	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
 	u32 val;
 
 	val = I915_READ(BXT_DE_PLL_CTL);
@@ -1077,7 +1131,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
 				    1))
 		DRM_ERROR("timeout waiting for DE PLL lock\n");
 
-	dev_priv->cdclk_pll.vco = vco;
+	dev_priv->cdclk.hw.vco = vco;
 }
 
 static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
@@ -1105,7 +1159,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
 		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
 		break;
 	default:
-		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
+		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
 		WARN_ON(vco != 0);
 
 		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
@@ -1124,11 +1178,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	if (dev_priv->cdclk_pll.vco != 0 &&
-	    dev_priv->cdclk_pll.vco != vco)
+	if (dev_priv->cdclk.hw.vco != 0 &&
+	    dev_priv->cdclk.hw.vco != vco)
 		bxt_de_pll_disable(dev_priv);
 
-	if (dev_priv->cdclk_pll.vco != vco)
+	if (dev_priv->cdclk.hw.vco != vco)
 		bxt_de_pll_enable(dev_priv, vco);
 
 	val = divider | skl_cdclk_decimal(cdclk);
@@ -1165,8 +1219,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 
 	intel_update_cdclk(dev_priv);
 
-	if (dev_priv->cdclk_pll.vco == 0 ||
-	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
+	if (dev_priv->cdclk.hw.vco == 0 ||
+	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
 		goto sanitize;
 
 	/* DPLL okay; verify the cdclock
@@ -1184,12 +1238,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
 
 	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
-		   skl_cdclk_decimal(dev_priv->cdclk_freq);
+		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
 	/*
 	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
 	 * enable otherwise.
 	 */
-	if (dev_priv->cdclk_freq >= 500000)
+	if (dev_priv->cdclk.hw.cdclk >= 500000)
 		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
 
 	if (cdctl == expected)
@@ -1200,10 +1254,10 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
 
 	/* force cdclk programming */
-	dev_priv->cdclk_freq = 0;
+	dev_priv->cdclk.hw.cdclk = 0;
 
 	/* force full PLL disable + enable */
-	dev_priv->cdclk_pll.vco = -1;
+	dev_priv->cdclk.hw.vco = -1;
 }
 
 void bxt_init_cdclk(struct drm_i915_private *dev_priv)
@@ -1212,7 +1266,8 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
 
 	bxt_sanitize_cdclk(dev_priv);
 
-	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
+	if (dev_priv->cdclk.hw.cdclk != 0 &&
+	    dev_priv->cdclk.hw.vco != 0)
 		return;
 
 	/*
@@ -1233,7 +1288,13 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
 
 void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
+	bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
+}
+
+bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
+			       const struct intel_cdclk_state *b)
+{
+	return memcmp(a, b, sizeof(*a)) == 0;
 }
 
 static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
@@ -1533,7 +1594,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
 		dev_priv->max_cdclk_freq = 400000;
 	} else {
 		/* otherwise assume cdclk is fixed */
-		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
+		dev_priv->max_cdclk_freq = dev_priv->cdclk.hw.cdclk;
 	}
 
 	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
@@ -1547,15 +1608,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
 
 void intel_update_cdclk(struct drm_i915_private *dev_priv)
 {
-	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
+	dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw);
 
-	if (INTEL_GEN(dev_priv) >= 9)
-		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
-				 dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
-				 dev_priv->cdclk_pll.ref);
-	else
-		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
-				 dev_priv->cdclk_freq);
+	DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
+			 dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco,
+			 dev_priv->cdclk.hw.ref);
 
 	/*
 	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
@@ -1565,7 +1622,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv)
 	 */
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		I915_WRITE(GMBUSFREQ_VLV,
-			   DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
+			   DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000));
 }
 
 static int pch_rawclk(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 519e5d663c5f..6c38ab299506 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -136,7 +136,7 @@ struct intel_limit {
 };
 
 /* returns HPLL frequency in kHz */
-static int valleyview_get_vco(struct drm_i915_private *dev_priv)
+int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
 {
 	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
 
@@ -172,7 +172,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
 			   const char *name, u32 reg)
 {
 	if (dev_priv->hpll_freq == 0)
-		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
+		dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
 
 	return vlv_get_cck_clock(dev_priv, name, reg,
 				 dev_priv->hpll_freq);
@@ -12436,7 +12436,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
 	 */
 	if (dev_priv->display.modeset_calc_cdclk) {
 		if (!intel_state->cdclk_pll_vco)
-			intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco;
+			intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco;
 		if (!intel_state->cdclk_pll_vco)
 			intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
 
@@ -12456,8 +12456,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
 		}
 
 		/* All pipes must be switched off while we change the cdclk. */
-		if (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
-		    intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) {
+		if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
+		    intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
 			ret = intel_modeset_all_pipes(state);
 			if (ret < 0)
 				return ret;
@@ -12874,8 +12874,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
 		if (dev_priv->display.modeset_commit_cdclk &&
-		    (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
-		     intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco))
+		    (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
+		     intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
 			dev_priv->display.modeset_commit_cdclk(state);
 
 		/*
@@ -14724,7 +14724,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
 	intel_update_cdclk(dev_priv);
 
-	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
+	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
 
 	intel_init_clock_gating(dev_priv);
 }
@@ -14897,7 +14897,7 @@ int intel_modeset_init(struct drm_device *dev)
 
 	intel_update_czclk(dev_priv);
 	intel_update_cdclk(dev_priv);
-	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
+	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
 
 	intel_shared_dpll_init(dev);
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 45ebc9632633..73a708b8d887 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -885,7 +885,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 	 * divide by 2000 and use that
 	 */
 	if (intel_dig_port->port == PORT_A)
-		return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
+		return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000);
 	else
 		return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8d93b7bda3ff..cc0122282a7b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1225,10 +1225,13 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
 void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
 void intel_update_cdclk(struct drm_i915_private *dev_priv);
 void intel_update_rawclk(struct drm_i915_private *dev_priv);
+bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
+			       const struct intel_cdclk_state *b);
 
 /* intel_display.c */
 enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
 void intel_update_rawclk(struct drm_i915_private *dev_priv);
+int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
 int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
 		      const char *name, u32 reg, int ref_freq);
 int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 463056d80f9b..385251e48c74 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -829,7 +829,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
 
 	/* WaFbcExceedCdClockThreshold:hsw,bdw */
 	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
-	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) {
+	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) {
 		fbc->no_fbc_reason = "pixel rate is too big";
 		return false;
 	}
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 1a6ff26dea20..cb50c527401f 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 	if (IS_PINEVIEW(dev_priv))
 		clock = KHz(dev_priv->rawclk_freq);
 	else
-		clock = KHz(dev_priv->cdclk_freq);
+		clock = KHz(dev_priv->cdclk.hw.cdclk);
 
 	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
 }
@@ -1333,7 +1333,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 	if (IS_G4X(dev_priv))
 		clock = KHz(dev_priv->rawclk_freq);
 	else
-		clock = KHz(dev_priv->cdclk_freq);
+		clock = KHz(dev_priv->cdclk.hw.cdclk);
 
 	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
 }
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 6d5efeb35823..14bbecc8f2ed 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -964,9 +964,12 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
 static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
 					  struct i915_power_well *power_well)
 {
+	struct intel_cdclk_state cdclk_state = {};
+
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
-	WARN_ON(dev_priv->cdclk_freq != dev_priv->display.get_cdclk(dev_priv));
+	dev_priv->display.get_cdclk(dev_priv, &cdclk_state);
+	WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state));
 
 	gen9_assert_dbuf_enabled(dev_priv);
 
-- 
2.10.2

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

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

* [PATCH v2 08/14] drm/i915: Track full cdclk state for the logical and actual cdclk frequencies
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (6 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-23 11:53   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH v2 09/14] drm/i915: Pass dev_priv to remainder of the cdclk functions ville.syrjala
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The current dev_cdclk vs. cdclk vs. atomic_cdclk_freq is quite a mess.
So here I'm introducing the "actual" and "logical" naming for our
cdclk state. "actual" is what we'll bash into the hardware and "logical"
is what everyone should use for state computaion/checking and whatnot.
We'll track both using the intel_cdclk_state as both will need other
differing parameters than just the actual cdclk frequency.

While doing that we can at the same time unify the appearance of the
.modeset_calc_cdclk() implementations a little bit.

v2: Commit dev_priv->cdclk.actual since that already has the
    new state by the time .modeset_commit_cdclk() is called.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  13 ++--
 drivers/gpu/drm/i915/intel_cdclk.c   | 123 ++++++++++++++++++++++-------------
 drivers/gpu/drm/i915/intel_display.c |  39 ++++++-----
 drivers/gpu/drm/i915/intel_dp.c      |   2 +-
 drivers/gpu/drm/i915/intel_drv.h     |  24 ++++---
 drivers/gpu/drm/i915/intel_pm.c      |   4 +-
 6 files changed, 121 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a4f1231ff8ca..b5a8d0f4cfbd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2237,18 +2237,19 @@ struct drm_i915_private {
 	unsigned int skl_preferred_vco_freq;
 	unsigned int max_cdclk_freq;
 
-	/*
-	 * For reading holding any crtc lock is sufficient,
-	 * for writing must hold all of them.
-	 */
-	unsigned int atomic_cdclk_freq;
-
 	unsigned int max_dotclk_freq;
 	unsigned int rawclk_freq;
 	unsigned int hpll_freq;
 	unsigned int czclk_freq;
 
 	struct {
+		/*
+		 * The current logical cdclk state.
+		 * For reading holding any crtc lock is sufficient,
+		 * for writing must hold all of them.
+		 */
+		struct intel_cdclk_state logical;
+		struct intel_cdclk_state actual;
 		struct intel_cdclk_state hw;
 	} cdclk;
 
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 13c3b5555473..08ae3b78b8ed 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -1368,12 +1368,26 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
 	int max_pixclk = intel_max_pixel_rate(state);
 	struct intel_atomic_state *intel_state =
 		to_intel_atomic_state(state);
+	int cdclk;
+
+	cdclk = vlv_calc_cdclk(dev_priv, max_pixclk);
+
+	if (cdclk > dev_priv->max_cdclk_freq) {
+		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+			      cdclk, dev_priv->max_cdclk_freq);
+		return -EINVAL;
+	}
 
-	intel_state->cdclk = intel_state->dev_cdclk =
-		vlv_calc_cdclk(dev_priv, max_pixclk);
+	intel_state->cdclk.logical.cdclk = cdclk;
 
-	if (!intel_state->active_crtcs)
-		intel_state->dev_cdclk = vlv_calc_cdclk(dev_priv, 0);
+	if (!intel_state->active_crtcs) {
+		cdclk = vlv_calc_cdclk(dev_priv, 0);
+
+		intel_state->cdclk.actual.cdclk = cdclk;
+	} else {
+		intel_state->cdclk.actual =
+			intel_state->cdclk.logical;
+	}
 
 	return 0;
 }
@@ -1382,9 +1396,7 @@ static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_device *dev = old_state->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_atomic_state *old_intel_state =
-		to_intel_atomic_state(old_state);
-	unsigned int req_cdclk = old_intel_state->dev_cdclk;
+	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
 
 	/*
 	 * FIXME: We can end up here with all power domains off, yet
@@ -1426,9 +1438,16 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
 		return -EINVAL;
 	}
 
-	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
-	if (!intel_state->active_crtcs)
-		intel_state->dev_cdclk = bdw_calc_cdclk(0);
+	intel_state->cdclk.logical.cdclk = cdclk;
+
+	if (!intel_state->active_crtcs) {
+		cdclk = bdw_calc_cdclk(0);
+
+		intel_state->cdclk.actual.cdclk = cdclk;
+	} else {
+		intel_state->cdclk.actual =
+			intel_state->cdclk.logical;
+	}
 
 	return 0;
 }
@@ -1436,9 +1455,7 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_device *dev = old_state->dev;
-	struct intel_atomic_state *old_intel_state =
-		to_intel_atomic_state(old_state);
-	unsigned int req_cdclk = old_intel_state->dev_cdclk;
+	unsigned int req_cdclk = to_i915(dev)->cdclk.actual.cdclk;
 
 	bdw_set_cdclk(dev, req_cdclk);
 }
@@ -1448,8 +1465,11 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
 	const int max_pixclk = intel_max_pixel_rate(state);
-	int vco = intel_state->cdclk_pll_vco;
-	int cdclk;
+	int cdclk, vco;
+
+	vco = intel_state->cdclk.logical.vco;
+	if (!vco)
+		vco = dev_priv->skl_preferred_vco_freq;
 
 	/*
 	 * FIXME should also account for plane ratio
@@ -1457,19 +1477,24 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 	 */
 	cdclk = skl_calc_cdclk(max_pixclk, vco);
 
-	/*
-	 * FIXME move the cdclk caclulation to
-	 * compute_config() so we can fail gracegully.
-	 */
 	if (cdclk > dev_priv->max_cdclk_freq) {
-		DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
-			  cdclk, dev_priv->max_cdclk_freq);
-		cdclk = dev_priv->max_cdclk_freq;
+		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+			      cdclk, dev_priv->max_cdclk_freq);
+		return -EINVAL;
 	}
 
-	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
-	if (!intel_state->active_crtcs)
-		intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
+	intel_state->cdclk.logical.vco = vco;
+	intel_state->cdclk.logical.cdclk = cdclk;
+
+	if (!intel_state->active_crtcs) {
+		cdclk = skl_calc_cdclk(0, vco);
+
+		intel_state->cdclk.actual.vco = vco;
+		intel_state->cdclk.actual.cdclk = cdclk;
+	} else {
+		intel_state->cdclk.actual =
+			intel_state->cdclk.logical;
+	}
 
 	return 0;
 }
@@ -1477,10 +1502,8 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-	struct intel_atomic_state *intel_state =
-		to_intel_atomic_state(old_state);
-	unsigned int req_cdclk = intel_state->dev_cdclk;
-	unsigned int req_vco = intel_state->cdclk_pll_vco;
+	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
+	unsigned int req_vco = dev_priv->cdclk.actual.vco;
 
 	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
 }
@@ -1491,22 +1514,39 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 	int max_pixclk = intel_max_pixel_rate(state);
 	struct intel_atomic_state *intel_state =
 		to_intel_atomic_state(state);
-	int cdclk;
+	int cdclk, vco;
 
-	if (IS_GEMINILAKE(dev_priv))
+	if (IS_GEMINILAKE(dev_priv)) {
 		cdclk = glk_calc_cdclk(max_pixclk);
-	else
+		vco = glk_de_pll_vco(dev_priv, cdclk);
+	} else {
 		cdclk = bxt_calc_cdclk(max_pixclk);
+		vco = bxt_de_pll_vco(dev_priv, cdclk);
+	}
+
+	if (cdclk > dev_priv->max_cdclk_freq) {
+		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+			      cdclk, dev_priv->max_cdclk_freq);
+		return -EINVAL;
+	}
 
-	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
+	intel_state->cdclk.logical.vco = vco;
+	intel_state->cdclk.logical.cdclk = cdclk;
 
 	if (!intel_state->active_crtcs) {
-		if (IS_GEMINILAKE(dev_priv))
+		if (IS_GEMINILAKE(dev_priv)) {
 			cdclk = glk_calc_cdclk(0);
-		else
+			vco = glk_de_pll_vco(dev_priv, cdclk);
+		} else {
 			cdclk = bxt_calc_cdclk(0);
+			vco = bxt_de_pll_vco(dev_priv, cdclk);
+		}
 
-		intel_state->dev_cdclk = cdclk;
+		intel_state->cdclk.actual.vco = vco;
+		intel_state->cdclk.actual.cdclk = cdclk;
+	} else {
+		intel_state->cdclk.actual =
+			intel_state->cdclk.logical;
 	}
 
 	return 0;
@@ -1515,15 +1555,8 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-	struct intel_atomic_state *old_intel_state =
-		to_intel_atomic_state(old_state);
-	unsigned int req_cdclk = old_intel_state->dev_cdclk;
-	unsigned int req_vco;
-
-	if (IS_GEMINILAKE(dev_priv))
-		req_vco = glk_de_pll_vco(dev_priv, req_cdclk);
-	else
-		req_vco = bxt_de_pll_vco(dev_priv, req_cdclk);
+	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
+	unsigned int req_vco = dev_priv->cdclk.actual.vco;
 
 	bxt_set_cdclk(dev_priv, req_cdclk, req_vco);
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6c38ab299506..fb3abb58b6ca 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12416,6 +12416,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
 
 	intel_state->modeset = true;
 	intel_state->active_crtcs = dev_priv->active_crtcs;
+	intel_state->cdclk.logical = dev_priv->cdclk.logical;
+	intel_state->cdclk.actual = dev_priv->cdclk.actual;
 
 	for_each_crtc_in_state(state, crtc, crtc_state, i) {
 		if (crtc_state->active)
@@ -12435,38 +12437,35 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
 	 * adjusted_mode bits in the crtc directly.
 	 */
 	if (dev_priv->display.modeset_calc_cdclk) {
-		if (!intel_state->cdclk_pll_vco)
-			intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco;
-		if (!intel_state->cdclk_pll_vco)
-			intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
-
 		ret = dev_priv->display.modeset_calc_cdclk(state);
 		if (ret < 0)
 			return ret;
 
 		/*
-		 * Writes to dev_priv->atomic_cdclk_freq must protected by
+		 * Writes to dev_priv->cdclk_locical must protected by
 		 * holding all the crtc locks, even if we don't end up
 		 * touching the hardware
 		 */
-		if (intel_state->cdclk != dev_priv->atomic_cdclk_freq) {
+		if (!intel_cdclk_state_compare(&dev_priv->cdclk.logical,
+					       &intel_state->cdclk.logical)) {
 			ret = intel_lock_all_pipes(state);
 			if (ret < 0)
 				return ret;
 		}
 
 		/* All pipes must be switched off while we change the cdclk. */
-		if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
-		    intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
+		if (!intel_cdclk_state_compare(&dev_priv->cdclk.actual,
+					       &intel_state->cdclk.actual)) {
 			ret = intel_modeset_all_pipes(state);
 			if (ret < 0)
 				return ret;
 		}
 
-		DRM_DEBUG_KMS("New cdclk calculated to be atomic %u, actual %u\n",
-			      intel_state->cdclk, intel_state->dev_cdclk);
+		DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n",
+			      intel_state->cdclk.logical.cdclk,
+			      intel_state->cdclk.actual.cdclk);
 	} else {
-		to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
+		to_intel_atomic_state(state)->cdclk.logical = dev_priv->cdclk.logical;
 	}
 
 	intel_modeset_clear_plls(state);
@@ -12569,7 +12568,7 @@ static int intel_atomic_check(struct drm_device *dev,
 		if (ret)
 			return ret;
 	} else {
-		intel_state->cdclk = dev_priv->atomic_cdclk_freq;
+		intel_state->cdclk.logical = dev_priv->cdclk.logical;
 	}
 
 	ret = drm_atomic_helper_check_planes(dev, state);
@@ -12874,8 +12873,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
 		if (dev_priv->display.modeset_commit_cdclk &&
-		    (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
-		     intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
+		    !intel_cdclk_state_compare(&dev_priv->cdclk.hw,
+					       &dev_priv->cdclk.actual))
 			dev_priv->display.modeset_commit_cdclk(state);
 
 		/*
@@ -13056,7 +13055,8 @@ static int intel_atomic_commit(struct drm_device *dev,
 		memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
 		       sizeof(intel_state->min_pixclk));
 		dev_priv->active_crtcs = intel_state->active_crtcs;
-		dev_priv->atomic_cdclk_freq = intel_state->cdclk;
+		dev_priv->cdclk.logical = intel_state->cdclk.logical;
+		dev_priv->cdclk.actual = intel_state->cdclk.actual;
 	}
 
 	drm_atomic_state_get(state);
@@ -13298,7 +13298,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
 		return DRM_PLANE_HELPER_NO_SCALING;
 
 	crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
-	cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
+	cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk;
 
 	if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock))
 		return DRM_PLANE_HELPER_NO_SCALING;
@@ -14723,8 +14723,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
 	intel_update_cdclk(dev_priv);
-
-	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
+	dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw;
 
 	intel_init_clock_gating(dev_priv);
 }
@@ -14897,7 +14896,7 @@ int intel_modeset_init(struct drm_device *dev)
 
 	intel_update_czclk(dev_priv);
 	intel_update_cdclk(dev_priv);
-	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
+	dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw;
 
 	intel_shared_dpll_init(dev);
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 73a708b8d887..4309509e8a34 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1734,7 +1734,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 			break;
 		}
 
-		to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco;
+		to_intel_atomic_state(pipe_config->base.state)->cdclk.logical.vco = vco;
 	}
 
 	if (!HAS_DDI(dev_priv))
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cc0122282a7b..d167ee458d63 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -333,13 +333,20 @@ struct dpll {
 struct intel_atomic_state {
 	struct drm_atomic_state base;
 
-	unsigned int cdclk;
-
-	/*
-	 * Calculated device cdclk, can be different from cdclk
-	 * only when all crtc's are DPMS off.
-	 */
-	unsigned int dev_cdclk;
+	struct {
+		/*
+		 * Logical state of cdclk (used for all scaling, watermark,
+		 * etc. calculations and checks). This is computed as if all
+		 * enabled crtcs were active.
+		 */
+		struct intel_cdclk_state logical;
+
+		/*
+		 * Actual state of cdclk, can be different from the logical
+		 * state only when all crtc's are DPMS off.
+		 */
+		struct intel_cdclk_state actual;
+	} cdclk;
 
 	bool dpll_set, modeset;
 
@@ -356,9 +363,6 @@ struct intel_atomic_state {
 	unsigned int active_crtcs;
 	unsigned int min_pixclk[I915_MAX_PIPES];
 
-	/* SKL/KBL Only */
-	unsigned int cdclk_pll_vco;
-
 	struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
 
 	/*
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 79e2be4216e4..fe522ec21502 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2095,7 +2095,7 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *cstate)
 		return 0;
 	if (WARN_ON(adjusted_mode->crtc_clock == 0))
 		return 0;
-	if (WARN_ON(intel_state->cdclk == 0))
+	if (WARN_ON(intel_state->cdclk.logical.cdclk == 0))
 		return 0;
 
 	/* The WM are computed with base on how long it takes to fill a single
@@ -2104,7 +2104,7 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *cstate)
 	linetime = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8,
 				     adjusted_mode->crtc_clock);
 	ips_linetime = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8,
-					 intel_state->cdclk);
+					 intel_state->cdclk.logical.cdclk);
 
 	return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
 	       PIPE_WM_LINETIME_TIME(linetime);
-- 
2.10.2

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

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

* [PATCH v2 09/14] drm/i915: Pass dev_priv to remainder of the cdclk functions
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (7 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH v2 08/14] drm/i915: Track full cdclk state for the logical and actual cdclk frequencies ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-23 12:01   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH v2 10/14] drm/i915: Pass the cdclk state to the set_cdclk() functions ville.syrjala
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Clean up the dev vs. dev_priv straggles that are making things
look inconsistentt.

v2: Deal with churn

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_cdclk.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 08ae3b78b8ed..2e998fa087a9 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -433,9 +433,8 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
 	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
 }
 
-static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
+static void vlv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
 	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
@@ -496,9 +495,8 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
 	intel_update_cdclk(dev_priv);
 }
 
-static void chv_set_cdclk(struct drm_device *dev, int cdclk)
+static void chv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
 	switch (cdclk) {
@@ -566,9 +564,8 @@ static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
 		cdclk_state->cdclk = 675000;
 }
 
-static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
+static void bdw_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t val, data;
 	int ret;
 
@@ -1363,8 +1360,7 @@ static int intel_max_pixel_rate(struct drm_atomic_state *state)
 
 static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
-	struct drm_device *dev = state->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(state->dev);
 	int max_pixclk = intel_max_pixel_rate(state);
 	struct intel_atomic_state *intel_state =
 		to_intel_atomic_state(state);
@@ -1394,8 +1390,7 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
 
 static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
-	struct drm_device *dev = old_state->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
 	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
 
 	/*
@@ -1410,9 +1405,9 @@ static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 
 	if (IS_CHERRYVIEW(dev_priv))
-		chv_set_cdclk(dev, req_cdclk);
+		chv_set_cdclk(dev_priv, req_cdclk);
 	else
-		vlv_set_cdclk(dev, req_cdclk);
+		vlv_set_cdclk(dev_priv, req_cdclk);
 
 	vlv_program_pfi_credits(dev_priv);
 
@@ -1454,10 +1449,10 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
 
 static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
-	struct drm_device *dev = old_state->dev;
-	unsigned int req_cdclk = to_i915(dev)->cdclk.actual.cdclk;
+	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
+	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
 
-	bdw_set_cdclk(dev, req_cdclk);
+	bdw_set_cdclk(dev_priv, req_cdclk);
 }
 
 static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
-- 
2.10.2

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

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

* [PATCH v2 10/14] drm/i915: Pass the cdclk state to the set_cdclk() functions
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (8 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH v2 09/14] drm/i915: Pass dev_priv to remainder of the cdclk functions ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-23 13:43   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 11/14] drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk() ville.syrjala
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Rather than passing all the different parameters (cdclk,vco so
far) sparately to the set_cdclk() functions, just pass the
entire cdclk state.

v2: Deal with churn

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_cdclk.c | 79 +++++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 2e998fa087a9..11a0f3e122c3 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -433,8 +433,10 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
 	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
 }
 
-static void vlv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
+			  const struct intel_cdclk_state *cdclk_state)
 {
+	int cdclk = cdclk_state->cdclk;
 	u32 val, cmd;
 
 	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
@@ -495,8 +497,10 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
 	intel_update_cdclk(dev_priv);
 }
 
-static void chv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+static void chv_set_cdclk(struct drm_i915_private *dev_priv,
+			  const struct intel_cdclk_state *cdclk_state)
 {
+	int cdclk = cdclk_state->cdclk;
 	u32 val, cmd;
 
 	switch (cdclk) {
@@ -564,8 +568,10 @@ static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
 		cdclk_state->cdclk = 675000;
 }
 
-static void bdw_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
+			  const struct intel_cdclk_state *cdclk_state)
 {
+	int cdclk = cdclk_state->cdclk;
 	uint32_t val, data;
 	int ret;
 
@@ -836,8 +842,10 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
 }
 
 static void skl_set_cdclk(struct drm_i915_private *dev_priv,
-			  int cdclk, int vco)
+			  const struct intel_cdclk_state *cdclk_state)
 {
+	int cdclk = cdclk_state->cdclk;
+	int vco = cdclk_state->vco;
 	u32 freq_select, pcu_ack;
 	int ret;
 
@@ -942,12 +950,17 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 
 void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-	skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
+	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
+
+	cdclk_state.cdclk = cdclk_state.ref;
+	cdclk_state.vco = 0;
+
+	skl_set_cdclk(dev_priv, &cdclk_state);
 }
 
 void skl_init_cdclk(struct drm_i915_private *dev_priv)
 {
-	int cdclk, vco;
+	struct intel_cdclk_state cdclk_state;
 
 	skl_sanitize_cdclk(dev_priv);
 
@@ -963,12 +976,14 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
 		return;
 	}
 
-	vco = dev_priv->skl_preferred_vco_freq;
-	if (vco == 0)
-		vco = 8100000;
-	cdclk = skl_calc_cdclk(0, vco);
+	cdclk_state = dev_priv->cdclk.hw;
+
+	cdclk_state.vco = dev_priv->skl_preferred_vco_freq;
+	if (cdclk_state.vco == 0)
+		cdclk_state.vco = 8100000;
+	cdclk_state.cdclk = skl_calc_cdclk(0, cdclk_state.vco);
 
-	skl_set_cdclk(dev_priv, cdclk, vco);
+	skl_set_cdclk(dev_priv, &cdclk_state);
 }
 
 static int bxt_calc_cdclk(int max_pixclk)
@@ -1132,8 +1147,10 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
 }
 
 static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
-			  int cdclk, int vco)
+			  const struct intel_cdclk_state *cdclk_state)
 {
+	int cdclk = cdclk_state->cdclk;
+	int vco = cdclk_state->vco;
 	u32 val, divider;
 	int ret;
 
@@ -1259,7 +1276,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 
 void bxt_init_cdclk(struct drm_i915_private *dev_priv)
 {
-	int cdclk, vco;
+	struct intel_cdclk_state cdclk_state;
 
 	bxt_sanitize_cdclk(dev_priv);
 
@@ -1267,25 +1284,33 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
 	    dev_priv->cdclk.hw.vco != 0)
 		return;
 
+	cdclk_state = dev_priv->cdclk.hw;
+
 	/*
 	 * FIXME:
 	 * - The initial CDCLK needs to be read from VBT.
 	 *   Need to make this change after VBT has changes for BXT.
 	 */
 	if (IS_GEMINILAKE(dev_priv)) {
-		cdclk = glk_calc_cdclk(0);
-		vco = glk_de_pll_vco(dev_priv, cdclk);
+		cdclk_state.cdclk = glk_calc_cdclk(0);
+		cdclk_state.vco = glk_de_pll_vco(dev_priv, cdclk_state.cdclk);
 	} else {
-		cdclk = bxt_calc_cdclk(0);
-		vco = bxt_de_pll_vco(dev_priv, cdclk);
+		cdclk_state.ref = dev_priv->cdclk.hw.ref;
+		cdclk_state.cdclk = bxt_calc_cdclk(0);
+		cdclk_state.vco = bxt_de_pll_vco(dev_priv, cdclk_state.cdclk);
 	}
 
-	bxt_set_cdclk(dev_priv, cdclk, vco);
+	bxt_set_cdclk(dev_priv, &cdclk_state);
 }
 
 void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-	bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
+	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
+
+	cdclk_state.cdclk = cdclk_state.ref;
+	cdclk_state.vco = 0;
+
+	bxt_set_cdclk(dev_priv, &cdclk_state);
 }
 
 bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
@@ -1391,7 +1416,6 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
 
 	/*
 	 * FIXME: We can end up here with all power domains off, yet
@@ -1405,9 +1429,9 @@ static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 
 	if (IS_CHERRYVIEW(dev_priv))
-		chv_set_cdclk(dev_priv, req_cdclk);
+		chv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 	else
-		vlv_set_cdclk(dev_priv, req_cdclk);
+		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 
 	vlv_program_pfi_credits(dev_priv);
 
@@ -1450,9 +1474,8 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
 
-	bdw_set_cdclk(dev_priv, req_cdclk);
+	bdw_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 }
 
 static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
@@ -1497,10 +1520,8 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
-	unsigned int req_vco = dev_priv->cdclk.actual.vco;
 
-	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
+	skl_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 }
 
 static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
@@ -1550,10 +1571,8 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
-	unsigned int req_vco = dev_priv->cdclk.actual.vco;
 
-	bxt_set_cdclk(dev_priv, req_cdclk, req_vco);
+	bxt_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 }
 
 static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
-- 
2.10.2

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

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

* [PATCH 11/14] drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk()
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (9 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH v2 10/14] drm/i915: Pass the cdclk state to the set_cdclk() functions ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-23 13:49   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 12/14] drm/i915: Nuke the VLV/CHV PFI programming power domain workaround ville.syrjala
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the vlv_program_pfi_credits() into vlv_set_cdclk() and
chv_set_cdclk() so that we can neuter vlv_modeset_commit_cdclk().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_cdclk.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 11a0f3e122c3..fe7a9e3a4f29 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -494,6 +494,8 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
 
 	mutex_unlock(&dev_priv->sb_lock);
 
+	vlv_program_pfi_credits(dev_priv);
+
 	intel_update_cdclk(dev_priv);
 }
 
@@ -533,6 +535,8 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
+	vlv_program_pfi_credits(dev_priv);
+
 	intel_update_cdclk(dev_priv);
 }
 
@@ -1433,7 +1437,6 @@ static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 	else
 		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 
-	vlv_program_pfi_credits(dev_priv);
 
 	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
 }
-- 
2.10.2

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

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

* [PATCH 12/14] drm/i915: Nuke the VLV/CHV PFI programming power domain workaround
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (10 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH 11/14] drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk() ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-23 13:52   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH v2 13/14] drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct .set_cdclk() hook ville.syrjala
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The hack to grab the pipe A power domain around VLV/CHV cdclk
programming has surely outlived its usefulness. We should be
hold sufficient power domains during any modeset, so let's just
nuke this hack.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_cdclk.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index fe7a9e3a4f29..bba077c4bd56 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -1421,24 +1421,10 @@ static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
 
-	/*
-	 * FIXME: We can end up here with all power domains off, yet
-	 * with a CDCLK frequency other than the minimum. To account
-	 * for this take the PIPE-A power domain, which covers the HW
-	 * blocks needed for the following programming. This can be
-	 * removed once it's guaranteed that we get here either with
-	 * the minimum CDCLK set, or the required power domains
-	 * enabled.
-	 */
-	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
-
 	if (IS_CHERRYVIEW(dev_priv))
 		chv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 	else
 		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
-
-
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
 }
 
 static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
-- 
2.10.2

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

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

* [PATCH v2 13/14] drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct .set_cdclk() hook
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (11 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH 12/14] drm/i915: Nuke the VLV/CHV PFI programming power domain workaround ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-23 14:03   ` Ander Conselvan De Oliveira
  2016-12-19 17:28 ` [PATCH 14/14] drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c ville.syrjala
  2016-12-19 18:15 ` ✓ Fi.CI.BAT: success for drm/i915: Introduce intel_cdclk_state (rev2) Patchwork
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

With the cdclk state, all the .modeset_commit_cdclk() hooks are
now pointless wrappers. Let's replace them with just a .set_cdclk()
function pointer. However let's wrap that in a small helper that
does the state comparison and prints a unified debug message across
all platforms. We didn't even have the debug print on all platforms
previously. This reduces the clutter in intel_atomic_commit_tail() a
little bit.

v2: Wrap .set_cdclk() in intel_set_cdclk()

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  3 +-
 drivers/gpu/drm/i915/intel_cdclk.c   | 71 +++++++++++++-----------------------
 drivers/gpu/drm/i915/intel_display.c |  5 +--
 drivers/gpu/drm/i915/intel_drv.h     |  2 +
 4 files changed, 30 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b5a8d0f4cfbd..faf753570a9a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -614,6 +614,8 @@ struct intel_cdclk_state;
 struct drm_i915_display_funcs {
 	void (*get_cdclk)(struct drm_i915_private *dev_priv,
 			  struct intel_cdclk_state *cdclk_state);
+	void (*set_cdclk)(struct drm_i915_private *dev_priv,
+			  const struct intel_cdclk_state *cdclk_state);
 	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
 	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
 	int (*compute_intermediate_wm)(struct drm_device *dev,
@@ -628,7 +630,6 @@ struct drm_i915_display_funcs {
 	int (*compute_global_watermarks)(struct drm_atomic_state *state);
 	void (*update_wm)(struct intel_crtc *crtc);
 	int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
-	void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
 	/* Returns the active state of the crtc, and if the crtc is active,
 	 * fills out the pipe-config with the hw state. */
 	bool (*get_pipe_config)(struct intel_crtc *,
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index bba077c4bd56..c2d995169528 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -855,9 +855,6 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
 
 	WARN_ON((cdclk == 24000) != (vco == 0));
 
-	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
-			 cdclk, vco);
-
 	mutex_lock(&dev_priv->rps.hw_lock);
 	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
 				SKL_CDCLK_PREPARE_FOR_CHANGE,
@@ -1158,9 +1155,6 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
 	u32 val, divider;
 	int ret;
 
-	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
-			 cdclk, vco);
-
 	/* cdclk = vco / 2 / div{1,1.5,2,4} */
 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
 	case 8:
@@ -1323,6 +1317,22 @@ bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
 	return memcmp(a, b, sizeof(*a)) == 0;
 }
 
+void intel_set_cdclk(struct drm_i915_private *dev_priv,
+		     const struct intel_cdclk_state *cdclk_state)
+{
+	if (intel_cdclk_state_compare(&dev_priv->cdclk.hw, cdclk_state))
+		return;
+
+	if (WARN_ON_ONCE(!dev_priv->display.set_cdclk))
+		return;
+
+	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz, VCO %d kHz, ref %d kHz\n",
+			 cdclk_state->cdclk, cdclk_state->vco,
+			 cdclk_state->ref);
+
+	dev_priv->display.set_cdclk(dev_priv, cdclk_state);
+}
+
 static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
 					  int pixel_rate)
 {
@@ -1417,16 +1427,6 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
 	return 0;
 }
 
-static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-
-	if (IS_CHERRYVIEW(dev_priv))
-		chv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
-	else
-		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
-}
-
 static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
@@ -1460,13 +1460,6 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
 	return 0;
 }
 
-static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-
-	bdw_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
-}
-
 static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
@@ -1506,13 +1499,6 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 	return 0;
 }
 
-static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-
-	skl_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
-}
-
 static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
@@ -1557,13 +1543,6 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 	return 0;
 }
 
-static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
-
-	bxt_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
-}
-
 static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
 {
 	int max_cdclk_freq = dev_priv->max_cdclk_freq;
@@ -1718,24 +1697,24 @@ void intel_update_rawclk(struct drm_i915_private *dev_priv)
 
 void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
 {
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			vlv_modeset_commit_cdclk;
+	if (IS_CHERRYVIEW(dev_priv)) {
+		dev_priv->display.set_cdclk = chv_set_cdclk;
+		dev_priv->display.modeset_calc_cdclk =
+			vlv_modeset_calc_cdclk;
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		dev_priv->display.set_cdclk = vlv_set_cdclk;
 		dev_priv->display.modeset_calc_cdclk =
 			vlv_modeset_calc_cdclk;
 	} else if (IS_BROADWELL(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			bdw_modeset_commit_cdclk;
+		dev_priv->display.set_cdclk = bdw_set_cdclk;
 		dev_priv->display.modeset_calc_cdclk =
 			bdw_modeset_calc_cdclk;
 	} else if (IS_GEN9_LP(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			bxt_modeset_commit_cdclk;
+		dev_priv->display.set_cdclk = bxt_set_cdclk;
 		dev_priv->display.modeset_calc_cdclk =
 			bxt_modeset_calc_cdclk;
 	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-		dev_priv->display.modeset_commit_cdclk =
-			skl_modeset_commit_cdclk;
+		dev_priv->display.set_cdclk = skl_set_cdclk;
 		dev_priv->display.modeset_calc_cdclk =
 			skl_modeset_calc_cdclk;
 	}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fb3abb58b6ca..409537011b28 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12872,10 +12872,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 	if (intel_state->modeset) {
 		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
-		if (dev_priv->display.modeset_commit_cdclk &&
-		    !intel_cdclk_state_compare(&dev_priv->cdclk.hw,
-					       &dev_priv->cdclk.actual))
-			dev_priv->display.modeset_commit_cdclk(state);
+		intel_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
 
 		/*
 		 * SKL workaround: bspec recommends we disable the SAGV when we
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d167ee458d63..40074827f01d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1231,6 +1231,8 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv);
 void intel_update_rawclk(struct drm_i915_private *dev_priv);
 bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
 			       const struct intel_cdclk_state *b);
+void intel_set_cdclk(struct drm_i915_private *dev_priv,
+		     const struct intel_cdclk_state *cdclk_state);
 
 /* intel_display.c */
 enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
-- 
2.10.2

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

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

* [PATCH 14/14] drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (12 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH v2 13/14] drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct .set_cdclk() hook ville.syrjala
@ 2016-12-19 17:28 ` ville.syrjala
  2016-12-23 14:06   ` Ander Conselvan De Oliveira
  2016-12-19 18:15 ` ✓ Fi.CI.BAT: success for drm/i915: Introduce intel_cdclk_state (rev2) Patchwork
  14 siblings, 1 reply; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 17:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move ilk_pipe_pixel_rate() next to its only caller
(intel_crtc_compute_pixel_rate()).

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 35 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 -
 drivers/gpu/drm/i915/intel_pm.c      | 33 ---------------------------------
 3 files changed, 35 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 409537011b28..5e18a598117c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6229,6 +6229,41 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
 		(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
 }
 
+static uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
+{
+	uint32_t pixel_rate;
+
+	pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
+
+	/*
+	 * We only use IF-ID interlacing. If we ever use
+	 * PF-ID we'll need to adjust the pixel_rate here.
+	 */
+
+	if (pipe_config->pch_pfit.enabled) {
+		uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
+		uint32_t pfit_size = pipe_config->pch_pfit.size;
+
+		pipe_w = pipe_config->pipe_src_w;
+		pipe_h = pipe_config->pipe_src_h;
+
+		pfit_w = (pfit_size >> 16) & 0xFFFF;
+		pfit_h = pfit_size & 0xFFFF;
+		if (pipe_w < pfit_w)
+			pipe_w = pfit_w;
+		if (pipe_h < pfit_h)
+			pipe_h = pfit_h;
+
+		if (WARN_ON(!pfit_w || !pfit_h))
+			return pixel_rate;
+
+		pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
+				     pfit_w * pfit_h);
+	}
+
+	return pixel_rate;
+}
+
 static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 40074827f01d..4fd03b73d863 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1791,7 +1791,6 @@ bool skl_wm_level_equals(const struct skl_wm_level *l1,
 bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries,
 				 const struct skl_ddb_entry *ddb,
 				 int ignore);
-uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
 bool ilk_disable_lp_wm(struct drm_device *dev);
 int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6);
 static inline int intel_enable_rc6(void)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index fe522ec21502..cd81b51291d6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1701,39 +1701,6 @@ static void i845_update_wm(struct intel_crtc *unused_crtc)
 	I915_WRITE(FW_BLC, fwater_lo);
 }
 
-uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
-{
-	uint32_t pixel_rate;
-
-	pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
-
-	/* We only use IF-ID interlacing. If we ever use PF-ID we'll need to
-	 * adjust the pixel_rate here. */
-
-	if (pipe_config->pch_pfit.enabled) {
-		uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
-		uint32_t pfit_size = pipe_config->pch_pfit.size;
-
-		pipe_w = pipe_config->pipe_src_w;
-		pipe_h = pipe_config->pipe_src_h;
-
-		pfit_w = (pfit_size >> 16) & 0xFFFF;
-		pfit_h = pfit_size & 0xFFFF;
-		if (pipe_w < pfit_w)
-			pipe_w = pfit_w;
-		if (pipe_h < pfit_h)
-			pipe_h = pfit_h;
-
-		if (WARN_ON(!pfit_w || !pfit_h))
-			return pixel_rate;
-
-		pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
-				     pfit_w * pfit_h);
-	}
-
-	return pixel_rate;
-}
-
 /* latency must be in 0.1us units. */
 static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency)
 {
-- 
2.10.2

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

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

* ✓ Fi.CI.BAT: success for drm/i915: Introduce intel_cdclk_state (rev2)
  2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
                   ` (13 preceding siblings ...)
  2016-12-19 17:28 ` [PATCH 14/14] drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c ville.syrjala
@ 2016-12-19 18:15 ` Patchwork
  14 siblings, 0 replies; 40+ messages in thread
From: Patchwork @ 2016-12-19 18:15 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Introduce intel_cdclk_state (rev2)
URL   : https://patchwork.freedesktop.org/series/16994/
State : success

== Summary ==

Series 16994v2 drm/i915: Introduce intel_cdclk_state
https://patchwork.freedesktop.org/api/1.0/series/16994/revisions/2/mbox/


fi-bdw-5557u     total:247  pass:233  dwarn:0   dfail:0   fail:0   skip:14 
fi-bsw-n3050     total:247  pass:208  dwarn:0   dfail:0   fail:0   skip:39 
fi-bxt-j4205     total:247  pass:225  dwarn:1   dfail:0   fail:0   skip:21 
fi-bxt-t5700     total:247  pass:220  dwarn:0   dfail:0   fail:0   skip:27 
fi-byt-j1900     total:247  pass:220  dwarn:0   dfail:0   fail:0   skip:27 
fi-byt-n2820     total:247  pass:216  dwarn:0   dfail:0   fail:0   skip:31 
fi-hsw-4770      total:247  pass:228  dwarn:0   dfail:0   fail:0   skip:19 
fi-hsw-4770r     total:247  pass:228  dwarn:0   dfail:0   fail:0   skip:19 
fi-ilk-650       total:247  pass:195  dwarn:0   dfail:0   fail:0   skip:52 
fi-ivb-3520m     total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-ivb-3770      total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-kbl-7500u     total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-skl-6260u     total:247  pass:234  dwarn:0   dfail:0   fail:0   skip:13 
fi-skl-6700hq    total:247  pass:227  dwarn:0   dfail:0   fail:0   skip:20 
fi-skl-6700k     total:247  pass:224  dwarn:3   dfail:0   fail:0   skip:20 
fi-skl-6770hq    total:247  pass:234  dwarn:0   dfail:0   fail:0   skip:13 
fi-snb-2520m     total:247  pass:216  dwarn:0   dfail:0   fail:0   skip:31 
fi-snb-2600      total:247  pass:215  dwarn:0   dfail:0   fail:0   skip:32 

cda2d70a4395323bcf064c81ee0f89d2de015544 drm-tip: 2016y-12m-19d-13h-00m-10s UTC integration manifest
d040558 drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c
21b5832 drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct .set_cdclk() hook
2062a1a drm/i915: Nuke the VLV/CHV PFI programming power domain workaround
d038c72 drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk()
78d684e drm/i915: Pass the cdclk state to the set_cdclk() functions
975f627 drm/i915: Pass dev_priv to remainder of the cdclk functions
7b6e5ff drm/i915: Track full cdclk state for the logical and actual cdclk frequencies
4ee69e5 drm/i915: Start moving the cdclk stuff into a distinct state structure
c09d12a drm/i915: Pass computed vco to bxt_set_cdclk()
a68c15c drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c
411c66a drm/i915: Clean up the .get_cdclk() assignment if ladder
970e62a drm/i915: s/get_display_clock_speed/get_cdclk/
0030606 drm/i915: Nuke intel_mode_max_pixclk()
5bd6e0f drm/i915: Store the pipe pixel rate in the crtc state

== Logs ==

For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3332/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state
  2016-12-19 17:28 ` [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state ville.syrjala
@ 2016-12-20 13:10   ` Ander Conselvan De Oliveira
  2016-12-20 13:29     ` Ville Syrjälä
  0 siblings, 1 reply; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-20 13:10 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Rather than recomptuing the pipe pixel rate on demand everwhere, let's
> just stick the precomputed value into the crtc state.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 31 ++++++++++++++++++++++++++-----
>  drivers/gpu/drm/i915/intel_drv.h     |  2 ++
>  drivers/gpu/drm/i915/intel_fbc.c     |  3 +--
>  drivers/gpu/drm/i915/intel_pm.c      | 14 +++++++-------
>  4 files changed, 36 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0b0d7e8be630..1d979041c52c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> 

[...]

> @@ -16919,7 +16938,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
                memset(crtc_state, 0, sizeof(*crtc_state));
                crtc_state->base.crtc = &crtc->base;
 
                crtc_state->base.active = crtc_state->base.enable =
                        dev_priv->display.get_pipe_config(crtc, crtc_state);
 
                crtc->base.enabled = crtc_state->base.enable;
                crtc->active = crtc_state->base.active;
 
                if (crtc_state->base.active) {
>  			dev_priv->active_crtcs |= 1 << crtc->pipe;
>  
>  			if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> -				pixclk = ilk_pipe_pixel_rate(crtc_state);
> +				pixclk = crtc_state->pixel_rate;

Aren't you reading 0 here, because of the memset above? As far as I can tell,
haswell_get_pipe_config() doesn't set crtc_state->pixel_rate.

>  			else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>  				pixclk = crtc_state->base.adjusted_mode.crtc_clock;
>  			else
> @@ -17031,6 +17050,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>  			 */
>  			crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
>  
> +			intel_crtc_compute_pixel_rate(crtc->config);
> +
>  			drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
>  			update_scanline_offset(crtc);
>  		}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f61ea43c7532..3969e786d566 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -541,6 +541,8 @@ struct intel_crtc_state {
>  	 * and get clipped at the edges. */
>  	int pipe_src_w, pipe_src_h;
>  
> +	unsigned int pixel_rate;
> +

Maybe add some comment about this parameter. This is not in kernel doc, but
having that already would probably make it easier for whoever does it in the
end.

Ander

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

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

* Re: [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk()
  2016-12-19 17:28 ` [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk() ville.syrjala
@ 2016-12-20 13:22   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-20 13:22 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> ilk_max_pixel_rate() will now give the "correct" pixel rate for all
> platforms, so let's kill rename it to intel_max_pixel_rate() and kill

Typo: "kill rename". With that fixed,

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> off intel_mode_max_pixclk().
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 41 ++++++-----------------------------
> -
>  1 file changed, 6 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 1d979041c52c..1e3f173a70e5 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -123,7 +123,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc,
> bool force);
>  static void ironlake_pfit_enable(struct intel_crtc *crtc);
>  static void intel_modeset_setup_hw_state(struct drm_device *dev);
>  static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
> -static int ilk_max_pixel_rate(struct drm_atomic_state *state);
> +static int intel_max_pixel_rate(struct drm_atomic_state *state);
>  static int glk_calc_cdclk(int max_pixclk);
>  static int bxt_calc_cdclk(int max_pixclk);
>  
> @@ -6566,40 +6566,11 @@ static int bxt_calc_cdclk(int max_pixclk)
>  		return 144000;
>  }
>  
> -/* Compute the max pixel clock for new configuration. */
> -static int intel_mode_max_pixclk(struct drm_device *dev,
> -				 struct drm_atomic_state *state)
> -{
> -	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *crtc_state;
> -	unsigned max_pixclk = 0, i;
> -	enum pipe pipe;
> -
> -	memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
> -	       sizeof(intel_state->min_pixclk));
> -
> -	for_each_crtc_in_state(state, crtc, crtc_state, i) {
> -		int pixclk = 0;
> -
> -		if (crtc_state->enable)
> -			pixclk = crtc_state->adjusted_mode.crtc_clock;
> -
> -		intel_state->min_pixclk[i] = pixclk;
> -	}
> -
> -	for_each_pipe(dev_priv, pipe)
> -		max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
> -
> -	return max_pixclk;
> -}
> -
>  static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
>  {
>  	struct drm_device *dev = state->dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	int max_pixclk = intel_mode_max_pixclk(dev, state);
> +	int max_pixclk = intel_max_pixel_rate(state);
>  	struct intel_atomic_state *intel_state =
>  		to_intel_atomic_state(state);
>  
> @@ -6615,7 +6586,7 @@ static int valleyview_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->dev);
> -	int max_pixclk = ilk_max_pixel_rate(state);
> +	int max_pixclk = intel_max_pixel_rate(state);
>  	struct intel_atomic_state *intel_state =
>  		to_intel_atomic_state(state);
>  	int cdclk;
> @@ -10290,7 +10261,7 @@ static int bdw_adjust_min_pipe_pixel_rate(struct
> intel_crtc_state *crtc_state,
>  }
>  
>  /* compute the max rate for new configuration */
> -static int ilk_max_pixel_rate(struct drm_atomic_state *state)
> +static int intel_max_pixel_rate(struct drm_atomic_state *state)
>  {
>  	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
>  	struct drm_i915_private *dev_priv = to_i915(state->dev);
> @@ -10422,7 +10393,7 @@ static int broadwell_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->dev);
>  	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> -	int max_pixclk = ilk_max_pixel_rate(state);
> +	int max_pixclk = intel_max_pixel_rate(state);
>  	int cdclk;
>  
>  	/*
> @@ -10458,7 +10429,7 @@ static int skl_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  {
>  	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
>  	struct drm_i915_private *dev_priv = to_i915(state->dev);
> -	const int max_pixclk = ilk_max_pixel_rate(state);
> +	const int max_pixclk = intel_max_pixel_rate(state);
>  	int vco = intel_state->cdclk_pll_vco;
>  	int cdclk;
>  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 03/14] drm/i915: s/get_display_clock_speed/get_cdclk/
  2016-12-19 17:28 ` [PATCH 03/14] drm/i915: s/get_display_clock_speed/get_cdclk/ ville.syrjala
@ 2016-12-20 13:27   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-20 13:27 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Rename the .get_display_clock_speed() hook to .get_cdclk().
> .get_cdclk() is more specific (which clock) and it's much
> shorter.

Indeed!

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h         |  2 +-
>  drivers/gpu/drm/i915/intel_display.c    | 93 +++++++++++++-------------------
> -
>  drivers/gpu/drm/i915/intel_runtime_pm.c |  3 +-
>  3 files changed, 39 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 6217f01d3c11..393b34fb2d1a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -611,7 +611,7 @@ struct intel_limit;
>  struct dpll;
>  
>  struct drm_i915_display_funcs {
> -	int (*get_display_clock_speed)(struct drm_i915_private *dev_priv);
> +	int (*get_cdclk)(struct drm_i915_private *dev_priv);
>  	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
>  	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
>  	int (*compute_intermediate_wm)(struct drm_device *dev,
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 1e3f173a70e5..bbfef348783b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5873,7 +5873,7 @@ static void intel_update_max_cdclk(struct
> drm_i915_private *dev_priv)
>  
>  static void intel_update_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	dev_priv->cdclk_freq = dev_priv-
> >display.get_display_clock_speed(dev_priv);
> +	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
>  
>  	if (INTEL_GEN(dev_priv) >= 9)
>  		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz,
> ref: %d kHz\n",
> @@ -6411,8 +6411,7 @@ static void valleyview_set_cdclk(struct drm_device *dev,
> int cdclk)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	u32 val, cmd;
>  
> -	WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
> -					!= dev_priv->cdclk_freq);
> +	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv-
> >cdclk_freq);
>  
>  	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
>  		cmd = 2;
> @@ -6476,8 +6475,7 @@ static void cherryview_set_cdclk(struct drm_device *dev,
> int cdclk)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	u32 val, cmd;
>  
> -	WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
> -						!= dev_priv->cdclk_freq);
> +	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv-
> >cdclk_freq);
>  
>  	switch (cdclk) {
>  	case 333333:
> @@ -7243,7 +7241,7 @@ static int intel_crtc_compute_config(struct intel_crtc
> *crtc,
>  	return 0;
>  }
>  
> -static int skylake_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int skylake_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	u32 cdctl;
>  
> @@ -7304,7 +7302,7 @@ static void bxt_de_pll_update(struct drm_i915_private
> *dev_priv)
>  		dev_priv->cdclk_pll.ref;
>  }
>  
> -static int broxton_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int broxton_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	u32 divider;
>  	int div, vco;
> @@ -7339,7 +7337,7 @@ static int broxton_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  	return DIV_ROUND_CLOSEST(vco, div);
>  }
>  
> -static int broadwell_get_display_clock_speed(struct drm_i915_private
> *dev_priv)
> +static int broadwell_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	uint32_t lcpll = I915_READ(LCPLL_CTL);
>  	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> @@ -7358,7 +7356,7 @@ static int broadwell_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  		return 675000;
>  }
>  
> -static int haswell_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int haswell_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	uint32_t lcpll = I915_READ(LCPLL_CTL);
>  	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> @@ -7375,33 +7373,33 @@ static int haswell_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  		return 540000;
>  }
>  
> -static int valleyview_get_display_clock_speed(struct drm_i915_private
> *dev_priv)
> +static int valleyview_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
>  				      CCK_DISPLAY_CLOCK_CONTROL);
>  }
>  
> -static int ilk_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int ilk_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 450000;
>  }
>  
> -static int i945_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int i945_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 400000;
>  }
>  
> -static int i915_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int i915_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 333333;
>  }
>  
> -static int i9xx_misc_get_display_clock_speed(struct drm_i915_private
> *dev_priv)
> +static int i9xx_misc_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 200000;
>  }
>  
> -static int pnv_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u16 gcfgc = 0;
> @@ -7426,7 +7424,7 @@ static int pnv_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  	}
>  }
>  
> -static int i915gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u16 gcfgc = 0;
> @@ -7446,12 +7444,12 @@ static int i915gm_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  	}
>  }
>  
> -static int i865_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int i865_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 266667;
>  }
>  
> -static int i85x_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u16 hpllcc = 0;
> @@ -7489,7 +7487,7 @@ static int i85x_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> -static int i830_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int i830_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 133333;
>  }
> @@ -7562,7 +7560,7 @@ static unsigned int intel_hpll_vco(struct
> drm_i915_private *dev_priv)
>  	return vco;
>  }
>  
> -static int gm45_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> @@ -7585,7 +7583,7 @@ static int gm45_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  	}
>  }
>  
> -static int i965gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	static const uint8_t div_3200[] = { 16, 10,  8 };
> @@ -7623,7 +7621,7 @@ static int i965gm_get_display_clock_speed(struct
> drm_i915_private *dev_priv)
>  	return 200000;
>  }
>  
> -static int g33_get_display_clock_speed(struct drm_i915_private *dev_priv)
> +static int g33_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
> @@ -16091,58 +16089,41 @@ void intel_init_display_hooks(struct
> drm_i915_private *dev_priv)
>  
>  	/* Returns the core display clock speed */
>  	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			skylake_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = skylake_get_cdclk;
>  	else if (IS_GEN9_LP(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			broxton_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = broxton_get_cdclk;
>  	else if (IS_BROADWELL(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			broadwell_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = broadwell_get_cdclk;
>  	else if (IS_HASWELL(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			haswell_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = haswell_get_cdclk;
>  	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			valleyview_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = valleyview_get_cdclk;
>  	else if (IS_GEN5(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			ilk_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = ilk_get_cdclk;
>  	else if (IS_I945G(dev_priv) || IS_I965G(dev_priv) ||
>  		 IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			i945_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i945_get_cdclk;
>  	else if (IS_GM45(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			gm45_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = gm45_get_cdclk;
>  	else if (IS_I965GM(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			i965gm_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i965gm_get_cdclk;
>  	else if (IS_PINEVIEW(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			pnv_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = pnv_get_cdclk;
>  	else if (IS_G33(dev_priv) || IS_G4X(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			g33_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = g33_get_cdclk;
>  	else if (IS_I915G(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			i915_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i915_get_cdclk;
>  	else if (IS_I945GM(dev_priv) || IS_I845G(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			i9xx_misc_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i9xx_misc_get_cdclk;
>  	else if (IS_I915GM(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			i915gm_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i915gm_get_cdclk;
>  	else if (IS_I865G(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			i865_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i865_get_cdclk;
>  	else if (IS_I85X(dev_priv))
> -		dev_priv->display.get_display_clock_speed =
> -			i85x_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i85x_get_cdclk;
>  	else { /* 830 */
>  		WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz
> CDCLK\n");
> -		dev_priv->display.get_display_clock_speed =
> -			i830_get_display_clock_speed;
> +		dev_priv->display.get_cdclk = i830_get_cdclk;
>  	}
>  
>  	if (IS_GEN5(dev_priv)) {
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c
> b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index c0b7e95b5b8e..6d5efeb35823 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -966,8 +966,7 @@ static void gen9_dc_off_power_well_enable(struct
> drm_i915_private *dev_priv,
>  {
>  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
>  
> -	WARN_ON(dev_priv->cdclk_freq !=
> -		dev_priv->display.get_display_clock_speed(dev_priv));
> +	WARN_ON(dev_priv->cdclk_freq != dev_priv-
> >display.get_cdclk(dev_priv));
>  
>  	gen9_assert_dbuf_enabled(dev_priv);
>  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state
  2016-12-20 13:10   ` Ander Conselvan De Oliveira
@ 2016-12-20 13:29     ` Ville Syrjälä
  2017-01-12 20:37       ` Rodrigo Vivi
  0 siblings, 1 reply; 40+ messages in thread
From: Ville Syrjälä @ 2016-12-20 13:29 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira; +Cc: intel-gfx, Rodrigo Vivi

On Tue, Dec 20, 2016 at 03:10:53PM +0200, Ander Conselvan De Oliveira wrote:
> On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Rather than recomptuing the pipe pixel rate on demand everwhere, let's
> > just stick the precomputed value into the crtc state.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 31 ++++++++++++++++++++++++++-----
> >  drivers/gpu/drm/i915/intel_drv.h     |  2 ++
> >  drivers/gpu/drm/i915/intel_fbc.c     |  3 +--
> >  drivers/gpu/drm/i915/intel_pm.c      | 14 +++++++-------
> >  4 files changed, 36 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 0b0d7e8be630..1d979041c52c 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > 
> 
> [...]
> 
> > @@ -16919,7 +16938,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>                 __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
>                 memset(crtc_state, 0, sizeof(*crtc_state));
>                 crtc_state->base.crtc = &crtc->base;
>  
>                 crtc_state->base.active = crtc_state->base.enable =
>                         dev_priv->display.get_pipe_config(crtc, crtc_state);
>  
>                 crtc->base.enabled = crtc_state->base.enable;
>                 crtc->active = crtc_state->base.active;
>  
>                 if (crtc_state->base.active) {
> >  			dev_priv->active_crtcs |= 1 << crtc->pipe;
> >  
> >  			if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> > -				pixclk = ilk_pipe_pixel_rate(crtc_state);
> > +				pixclk = crtc_state->pixel_rate;
> 
> Aren't you reading 0 here, because of the memset above? As far as I can tell,
> haswell_get_pipe_config() doesn't set crtc_state->pixel_rate.

Hmm, yeah. Which means this whole piece of min_pixclk[] code is in
the wrong place. You can't know the pixel rate until you know the
clock, and you don't know that until you've done the full readout
(meaning the encoder .get_config() hooks have been called as well).

> 
> >  			else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >  				pixclk = crtc_state->base.adjusted_mode.crtc_clock;
> >  			else
> > @@ -17031,6 +17050,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
> >  			 */
> >  			crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
> >  
> > +			intel_crtc_compute_pixel_rate(crtc->config);
> > +
> >  			drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
> >  			update_scanline_offset(crtc);
> >  		}
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index f61ea43c7532..3969e786d566 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -541,6 +541,8 @@ struct intel_crtc_state {
> >  	 * and get clipped at the edges. */
> >  	int pipe_src_w, pipe_src_h;
> >  
> > +	unsigned int pixel_rate;
> > +
> 
> Maybe add some comment about this parameter. This is not in kernel doc, but
> having that already would probably make it easier for whoever does it in the
> end.
> 
> Ander

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

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

* Re: [PATCH 04/14] drm/i915: Clean up the .get_cdclk() assignment if ladder
  2016-12-19 17:28 ` [PATCH 04/14] drm/i915: Clean up the .get_cdclk() assignment if ladder ville.syrjala
@ 2016-12-20 13:42   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-20 13:42 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx, Jani Nikula; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Let's clean up the mess we have in the if ladder that assigns the
> .get_cdclk() hooks. The grouping of the platforms by the function
> results in a thing that's not really legible, so let's do it the
> other way around and order the if ladder by platform and duplicate
> whatever assignments we need.
> 
> To further avoid confusion with the function names let's rename
> them to just fixed_<freq>_get_cdclk(). The other option would
> be to duplicate the functions entirely but it seems quite
> pointless to do that since each one just returns a fixed value.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 41 +++++++++++++++++++++------------
> ---
>  1 file changed, 24 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index bbfef348783b..29f91e799272 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -7379,22 +7379,22 @@ static int valleyview_get_cdclk(struct
> drm_i915_private *dev_priv)
>  				      CCK_DISPLAY_CLOCK_CONTROL);
>  }
>  
> -static int ilk_get_cdclk(struct drm_i915_private *dev_priv)
> +static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 450000;
>  }
>  
> -static int i945_get_cdclk(struct drm_i915_private *dev_priv)
> +static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 400000;
>  }
>  
> -static int i915_get_cdclk(struct drm_i915_private *dev_priv)
> +static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 333333;
>  }
>  
> -static int i9xx_misc_get_cdclk(struct drm_i915_private *dev_priv)
> +static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 200000;
>  }
> @@ -7444,7 +7444,7 @@ static int i915gm_get_cdclk(struct drm_i915_private
> *dev_priv)
>  	}
>  }
>  
> -static int i865_get_cdclk(struct drm_i915_private *dev_priv)
> +static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 266667;
>  }
> @@ -7487,7 +7487,7 @@ static int i85x_get_cdclk(struct drm_i915_private
> *dev_priv)
>  	return 0;
>  }
>  
> -static int i830_get_cdclk(struct drm_i915_private *dev_priv)
> +static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	return 133333;
>  }
> @@ -16098,32 +16098,39 @@ void intel_init_display_hooks(struct
> drm_i915_private *dev_priv)
>  		dev_priv->display.get_cdclk = haswell_get_cdclk;
>  	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>  		dev_priv->display.get_cdclk = valleyview_get_cdclk;
> +	else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
>  	else if (IS_GEN5(dev_priv))
> -		dev_priv->display.get_cdclk = ilk_get_cdclk;
> -	else if (IS_I945G(dev_priv) || IS_I965G(dev_priv) ||
> -		 IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
> -		dev_priv->display.get_cdclk = i945_get_cdclk;
> +		dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
>  	else if (IS_GM45(dev_priv))
>  		dev_priv->display.get_cdclk = gm45_get_cdclk;
> +	else if (IS_G4X(dev_priv))
> +		dev_priv->display.get_cdclk = g33_get_cdclk;
>  	else if (IS_I965GM(dev_priv))
>  		dev_priv->display.get_cdclk = i965gm_get_cdclk;
> +	else if (IS_I965G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
>  	else if (IS_PINEVIEW(dev_priv))
>  		dev_priv->display.get_cdclk = pnv_get_cdclk;
> -	else if (IS_G33(dev_priv) || IS_G4X(dev_priv))
> +	else if (IS_G33(dev_priv))
>  		dev_priv->display.get_cdclk = g33_get_cdclk;
> -	else if (IS_I915G(dev_priv))
> -		dev_priv->display.get_cdclk = i915_get_cdclk;
> -	else if (IS_I945GM(dev_priv) || IS_I845G(dev_priv))
> -		dev_priv->display.get_cdclk = i9xx_misc_get_cdclk;
> +	else if (IS_I945GM(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> +	else if (IS_I945G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
>  	else if (IS_I915GM(dev_priv))
>  		dev_priv->display.get_cdclk = i915gm_get_cdclk;
> +	else if (IS_I915G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
>  	else if (IS_I865G(dev_priv))
> -		dev_priv->display.get_cdclk = i865_get_cdclk;
> +		dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
>  	else if (IS_I85X(dev_priv))
>  		dev_priv->display.get_cdclk = i85x_get_cdclk;
> +	else  if (IS_I845G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
>  	else { /* 830 */
>  		WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz
> CDCLK\n");
> -		dev_priv->display.get_cdclk = i830_get_cdclk;
> +		dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
>  	}
>  
>  	if (IS_GEN5(dev_priv)) {

I think this is a worthwhile patch even if we are doing the improvements
discussed in the v1 thread, so

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

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

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

* Re: [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c
  2016-12-19 17:28 ` [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c ville.syrjala
@ 2016-12-22 13:10   ` Ander Conselvan De Oliveira
  2016-12-22 13:16     ` Joonas Lahtinen
  0 siblings, 1 reply; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-22 13:10 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Let's try to shrink intel_display.c a bit by moving the cdclk/rawclk
> stuff to a new file. It's all reasonably self contained so we don't
> even have to add that many non-static symbols.
> 
> We'll also take the opportunity to shuffle around the functions a bit
> to get things in a more consistent order based on the platform.

Hmm, maybe this is the moment to add some kerneldoc to this stuff, or Daniel
might be grumpy? :)

The new file makes sense, didn't really check the move line by line, but

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>


> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile        |    1 +
>  drivers/gpu/drm/i915/intel_cdclk.c   | 1690 +++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_display.c | 2115 ++++-----------------------------
> -
>  drivers/gpu/drm/i915/intel_drv.h     |    9 +-
>  4 files changed, 1922 insertions(+), 1893 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_cdclk.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 5196509e71cf..3f5c21b76e85 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -70,6 +70,7 @@ i915-y += intel_audio.o \
>  	  intel_atomic.o \
>  	  intel_atomic_plane.o \
>  	  intel_bios.o \
> +	  intel_cdclk.o \
>  	  intel_color.o \
>  	  intel_display.o \
>  	  intel_dpio_phy.o \
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> b/drivers/gpu/drm/i915/intel_cdclk.c
> new file mode 100644
> index 000000000000..1804c43553b7
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -0,0 +1,1690 @@
> +/*
> + * Copyright © 2006-2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include "intel_drv.h"
> +
> +static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	return 133333;
> +}
> +
> +static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	return 200000;
> +}
> +
> +static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	return 266667;
> +}
> +
> +static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	return 333333;
> +}
> +
> +static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	return 400000;
> +}
> +
> +static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	return 450000;
> +}
> +
> +static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
> +	u16 hpllcc = 0;
> +
> +	/*
> +	 * 852GM/852GMV only supports 133 MHz and the HPLLCC
> +	 * encoding is different :(
> +	 * FIXME is this the right way to detect 852GM/852GMV?
> +	 */
> +	if (pdev->revision == 0x1)
> +		return 133333;
> +
> +	pci_bus_read_config_word(pdev->bus,
> +				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
> +
> +	/* Assume that the hardware is in the high speed state.  This
> +	 * should be the default.
> +	 */
> +	switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
> +	case GC_CLOCK_133_200:
> +	case GC_CLOCK_133_200_2:
> +	case GC_CLOCK_100_200:
> +		return 200000;
> +	case GC_CLOCK_166_250:
> +		return 250000;
> +	case GC_CLOCK_100_133:
> +		return 133333;
> +	case GC_CLOCK_133_266:
> +	case GC_CLOCK_133_266_2:
> +	case GC_CLOCK_166_266:
> +		return 266667;
> +	}
> +
> +	/* Shouldn't happen */
> +	return 0;
> +}
> +
> +static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
> +	u16 gcfgc = 0;
> +
> +	pci_read_config_word(pdev, GCFGC, &gcfgc);
> +
> +	if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
> +		return 133333;
> +
> +	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> +	case GC_DISPLAY_CLOCK_333_MHZ:
> +		return 333333;
> +	default:
> +	case GC_DISPLAY_CLOCK_190_200_MHZ:
> +		return 190000;
> +	}
> +}
> +
> +static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
> +{
> +	static const unsigned int blb_vco[8] = {
> +		[0] = 3200000,
> +		[1] = 4000000,
> +		[2] = 5333333,
> +		[3] = 4800000,
> +		[4] = 6400000,
> +	};
> +	static const unsigned int pnv_vco[8] = {
> +		[0] = 3200000,
> +		[1] = 4000000,
> +		[2] = 5333333,
> +		[3] = 4800000,
> +		[4] = 2666667,
> +	};
> +	static const unsigned int cl_vco[8] = {
> +		[0] = 3200000,
> +		[1] = 4000000,
> +		[2] = 5333333,
> +		[3] = 6400000,
> +		[4] = 3333333,
> +		[5] = 3566667,
> +		[6] = 4266667,
> +	};
> +	static const unsigned int elk_vco[8] = {
> +		[0] = 3200000,
> +		[1] = 4000000,
> +		[2] = 5333333,
> +		[3] = 4800000,
> +	};
> +	static const unsigned int ctg_vco[8] = {
> +		[0] = 3200000,
> +		[1] = 4000000,
> +		[2] = 5333333,
> +		[3] = 6400000,
> +		[4] = 2666667,
> +		[5] = 4266667,
> +	};
> +	const unsigned int *vco_table;
> +	unsigned int vco;
> +	uint8_t tmp = 0;
> +
> +	/* FIXME other chipsets? */
> +	if (IS_GM45(dev_priv))
> +		vco_table = ctg_vco;
> +	else if (IS_G4X(dev_priv))
> +		vco_table = elk_vco;
> +	else if (IS_I965GM(dev_priv))
> +		vco_table = cl_vco;
> +	else if (IS_PINEVIEW(dev_priv))
> +		vco_table = pnv_vco;
> +	else if (IS_G33(dev_priv))
> +		vco_table = blb_vco;
> +	else
> +		return 0;
> +
> +	tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
> +
> +	vco = vco_table[tmp & 0x7];
> +	if (vco == 0)
> +		DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
> +	else
> +		DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
> +
> +	return vco;
> +}
> +
> +static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
> +	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
> +	static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
> +	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
> +	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
> +	const uint8_t *div_table;
> +	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> +	uint16_t tmp = 0;
> +
> +	pci_read_config_word(pdev, GCFGC, &tmp);
> +
> +	cdclk_sel = (tmp >> 4) & 0x7;
> +
> +	if (cdclk_sel >= ARRAY_SIZE(div_3200))
> +		goto fail;
> +
> +	switch (vco) {
> +	case 3200000:
> +		div_table = div_3200;
> +		break;
> +	case 4000000:
> +		div_table = div_4000;
> +		break;
> +	case 4800000:
> +		div_table = div_4800;
> +		break;
> +	case 5333333:
> +		div_table = div_5333;
> +		break;
> +	default:
> +		goto fail;
> +	}
> +
> +	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> +
> +fail:
> +	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%08x\n",
> +		  vco, tmp);
> +	return 190476;
> +}
> +
> +static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
> +	u16 gcfgc = 0;
> +
> +	pci_read_config_word(pdev, GCFGC, &gcfgc);
> +
> +	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> +	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
> +		return 266667;
> +	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
> +		return 333333;
> +	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
> +		return 444444;
> +	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
> +		return 200000;
> +	default:
> +		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
> +	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
> +		return 133333;
> +	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
> +		return 166667;
> +	}
> +}
> +
> +static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
> +	static const uint8_t div_3200[] = { 16, 10,  8 };
> +	static const uint8_t div_4000[] = { 20, 12, 10 };
> +	static const uint8_t div_5333[] = { 24, 16, 14 };
> +	const uint8_t *div_table;
> +	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> +	uint16_t tmp = 0;
> +
> +	pci_read_config_word(pdev, GCFGC, &tmp);
> +
> +	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
> +
> +	if (cdclk_sel >= ARRAY_SIZE(div_3200))
> +		goto fail;
> +
> +	switch (vco) {
> +	case 3200000:
> +		div_table = div_3200;
> +		break;
> +	case 4000000:
> +		div_table = div_4000;
> +		break;
> +	case 5333333:
> +		div_table = div_5333;
> +		break;
> +	default:
> +		goto fail;
> +	}
> +
> +	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> +
> +fail:
> +	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%04x\n",
> +		  vco, tmp);
> +	return 200000;
> +}
> +
> +static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
> +	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> +	uint16_t tmp = 0;
> +
> +	pci_read_config_word(pdev, GCFGC, &tmp);
> +
> +	cdclk_sel = (tmp >> 12) & 0x1;
> +
> +	switch (vco) {
> +	case 2666667:
> +	case 4000000:
> +	case 5333333:
> +		return cdclk_sel ? 333333 : 222222;
> +	case 3200000:
> +		return cdclk_sel ? 320000 : 228571;
> +	default:
> +		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u,
> CFGC=0x%04x\n",
> +			  vco, tmp);
> +		return 222222;
> +	}
> +}
> +
> +static int hsw_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	uint32_t lcpll = I915_READ(LCPLL_CTL);
> +	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> +
> +	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> +		return 800000;
> +	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> +		return 450000;
> +	else if (freq == LCPLL_CLK_FREQ_450)
> +		return 450000;
> +	else if (IS_HSW_ULT(dev_priv))
> +		return 337500;
> +	else
> +		return 540000;
> +}
> +
> +static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
> +			  int max_pixclk)
> +{
> +	int freq_320 = (dev_priv->hpll_freq <<  1) % 320000 != 0 ?
> +		333333 : 320000;
> +	int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
> +
> +	/*
> +	 * We seem to get an unstable or solid color picture at 200MHz.
> +	 * Not sure what's wrong. For now use 200MHz only when all pipes
> +	 * are off.
> +	 */
> +	if (!IS_CHERRYVIEW(dev_priv) &&
> +	    max_pixclk > freq_320*limit/100)
> +		return 400000;
> +	else if (max_pixclk > 266667*limit/100)
> +		return freq_320;
> +	else if (max_pixclk > 0)
> +		return 266667;
> +	else
> +		return 200000;
> +}
> +
> +static int vlv_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
> +				      CCK_DISPLAY_CLOCK_CONTROL);
> +}
> +
> +static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
> +{
> +	unsigned int credits, default_credits;
> +
> +	if (IS_CHERRYVIEW(dev_priv))
> +		default_credits = PFI_CREDIT(12);
> +	else
> +		default_credits = PFI_CREDIT(8);
> +
> +	if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
> +		/* CHV suggested value is 31 or 63 */
> +		if (IS_CHERRYVIEW(dev_priv))
> +			credits = PFI_CREDIT_63;
> +		else
> +			credits = PFI_CREDIT(15);
> +	} else {
> +		credits = default_credits;
> +	}
> +
> +	/*
> +	 * WA - write default credits before re-programming
> +	 * FIXME: should we also set the resend bit here?
> +	 */
> +	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> +		   default_credits);
> +
> +	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> +		   credits | PFI_CREDIT_RESEND);
> +
> +	/*
> +	 * FIXME is this guaranteed to clear
> +	 * immediately or should we poll for it?
> +	 */
> +	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
> +}
> +
> +static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	u32 val, cmd;
> +
> +	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv-
> >cdclk_freq);
> +
> +	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
> +		cmd = 2;
> +	else if (cdclk == 266667)
> +		cmd = 1;
> +	else
> +		cmd = 0;
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> +	val &= ~DSPFREQGUAR_MASK;
> +	val |= (cmd << DSPFREQGUAR_SHIFT);
> +	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> +	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> +		      DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
> +		     50)) {
> +		DRM_ERROR("timed out waiting for CDclk change\n");
> +	}
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	mutex_lock(&dev_priv->sb_lock);
> +
> +	if (cdclk == 400000) {
> +		u32 divider;
> +
> +		divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1,
> +					    cdclk) - 1;
> +
> +		/* adjust cdclk divider */
> +		val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
> +		val &= ~CCK_FREQUENCY_VALUES;
> +		val |= divider;
> +		vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
> +
> +		if (wait_for((vlv_cck_read(dev_priv,
> CCK_DISPLAY_CLOCK_CONTROL) &
> +			      CCK_FREQUENCY_STATUS) == (divider <<
> CCK_FREQUENCY_STATUS_SHIFT),
> +			     50))
> +			DRM_ERROR("timed out waiting for CDclk change\n");
> +	}
> +
> +	/* adjust self-refresh exit latency value */
> +	val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
> +	val &= ~0x7f;
> +
> +	/*
> +	 * For high bandwidth configs, we set a higher latency in the bunit
> +	 * so that the core display fetch happens in time to avoid underruns.
> +	 */
> +	if (cdclk == 400000)
> +		val |= 4500 / 250; /* 4.5 usec */
> +	else
> +		val |= 3000 / 250; /* 3.0 usec */
> +	vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
> +
> +	mutex_unlock(&dev_priv->sb_lock);
> +
> +	intel_update_cdclk(dev_priv);
> +}
> +
> +static void chv_set_cdclk(struct drm_device *dev, int cdclk)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	u32 val, cmd;
> +
> +	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv-
> >cdclk_freq);
> +
> +	switch (cdclk) {
> +	case 333333:
> +	case 320000:
> +	case 266667:
> +	case 200000:
> +		break;
> +	default:
> +		MISSING_CASE(cdclk);
> +		return;
> +	}
> +
> +	/*
> +	 * Specs are full of misinformation, but testing on actual
> +	 * hardware has shown that we just need to write the desired
> +	 * CCK divider into the Punit register.
> +	 */
> +	cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> +	val &= ~DSPFREQGUAR_MASK_CHV;
> +	val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
> +	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> +	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> +		      DSPFREQSTAT_MASK_CHV) == (cmd <<
> DSPFREQSTAT_SHIFT_CHV),
> +		     50)) {
> +		DRM_ERROR("timed out waiting for CDclk change\n");
> +	}
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	intel_update_cdclk(dev_priv);
> +}
> +
> +static int bdw_calc_cdclk(int max_pixclk)
> +{
> +	if (max_pixclk > 540000)
> +		return 675000;
> +	else if (max_pixclk > 450000)
> +		return 540000;
> +	else if (max_pixclk > 337500)
> +		return 450000;
> +	else
> +		return 337500;
> +}
> +
> +static int bdw_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	uint32_t lcpll = I915_READ(LCPLL_CTL);
> +	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> +
> +	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> +		return 800000;
> +	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> +		return 450000;
> +	else if (freq == LCPLL_CLK_FREQ_450)
> +		return 450000;
> +	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
> +		return 540000;
> +	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
> +		return 337500;
> +	else
> +		return 675000;
> +}
> +
> +static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	uint32_t val, data;
> +	int ret;
> +
> +	if (WARN((I915_READ(LCPLL_CTL) &
> +		  (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
> +		   LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
> +		   LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
> +		   LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
> +		 "trying to change cdclk frequency with cdclk not
> enabled\n"))
> +		return;
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	ret = sandybridge_pcode_write(dev_priv,
> +				      BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ,
> 0x0);
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +	if (ret) {
> +		DRM_ERROR("failed to inform pcode about cdclk change\n");
> +		return;
> +	}
> +
> +	val = I915_READ(LCPLL_CTL);
> +	val |= LCPLL_CD_SOURCE_FCLK;
> +	I915_WRITE(LCPLL_CTL, val);
> +
> +	if (wait_for_us(I915_READ(LCPLL_CTL) &
> +			LCPLL_CD_SOURCE_FCLK_DONE, 1))
> +		DRM_ERROR("Switching to FCLK failed\n");
> +
> +	val = I915_READ(LCPLL_CTL);
> +	val &= ~LCPLL_CLK_FREQ_MASK;
> +
> +	switch (cdclk) {
> +	case 450000:
> +		val |= LCPLL_CLK_FREQ_450;
> +		data = 0;
> +		break;
> +	case 540000:
> +		val |= LCPLL_CLK_FREQ_54O_BDW;
> +		data = 1;
> +		break;
> +	case 337500:
> +		val |= LCPLL_CLK_FREQ_337_5_BDW;
> +		data = 2;
> +		break;
> +	case 675000:
> +		val |= LCPLL_CLK_FREQ_675_BDW;
> +		data = 3;
> +		break;
> +	default:
> +		WARN(1, "invalid cdclk frequency\n");
> +		return;
> +	}
> +
> +	I915_WRITE(LCPLL_CTL, val);
> +
> +	val = I915_READ(LCPLL_CTL);
> +	val &= ~LCPLL_CD_SOURCE_FCLK;
> +	I915_WRITE(LCPLL_CTL, val);
> +
> +	if (wait_for_us((I915_READ(LCPLL_CTL) &
> +			LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
> +		DRM_ERROR("Switching back to LCPLL failed\n");
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
> +
> +	intel_update_cdclk(dev_priv);
> +
> +	WARN(cdclk != dev_priv->cdclk_freq,
> +	     "cdclk requested %d kHz but got %d kHz\n",
> +	     cdclk, dev_priv->cdclk_freq);
> +}
> +
> +static int skl_calc_cdclk(int max_pixclk, int vco)
> +{
> +	if (vco == 8640000) {
> +		if (max_pixclk > 540000)
> +			return 617143;
> +		else if (max_pixclk > 432000)
> +			return 540000;
> +		else if (max_pixclk > 308571)
> +			return 432000;
> +		else
> +			return 308571;
> +	} else {
> +		if (max_pixclk > 540000)
> +			return 675000;
> +		else if (max_pixclk > 450000)
> +			return 540000;
> +		else if (max_pixclk > 337500)
> +			return 450000;
> +		else
> +			return 337500;
> +	}
> +}
> +
> +static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> +{
> +	u32 val;
> +
> +	dev_priv->cdclk_pll.ref = 24000;
> +	dev_priv->cdclk_pll.vco = 0;
> +
> +	val = I915_READ(LCPLL1_CTL);
> +	if ((val & LCPLL_PLL_ENABLE) == 0)
> +		return;
> +
> +	if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
> +		return;
> +
> +	val = I915_READ(DPLL_CTRL1);
> +
> +	if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
> +			    DPLL_CTRL1_SSC(SKL_DPLL0) |
> +			    DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
> +		    DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
> +		return;
> +
> +	switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
> +	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
> +	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
> +	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
> +	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
> +		dev_priv->cdclk_pll.vco = 8100000;
> +		break;
> +	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
> +	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
> +		dev_priv->cdclk_pll.vco = 8640000;
> +		break;
> +	default:
> +		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> +		break;
> +	}
> +}
> +
> +static int skl_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	u32 cdctl;
> +
> +	skl_dpll0_update(dev_priv);
> +
> +	if (dev_priv->cdclk_pll.vco == 0)
> +		return dev_priv->cdclk_pll.ref;
> +
> +	cdctl = I915_READ(CDCLK_CTL);
> +
> +	if (dev_priv->cdclk_pll.vco == 8640000) {
> +		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> +		case CDCLK_FREQ_450_432:
> +			return 432000;
> +		case CDCLK_FREQ_337_308:
> +			return 308571;
> +		case CDCLK_FREQ_540:
> +			return 540000;
> +		case CDCLK_FREQ_675_617:
> +			return 617143;
> +		default:
> +			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> +		}
> +	} else {
> +		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> +		case CDCLK_FREQ_450_432:
> +			return 450000;
> +		case CDCLK_FREQ_337_308:
> +			return 337500;
> +		case CDCLK_FREQ_540:
> +			return 540000;
> +		case CDCLK_FREQ_675_617:
> +			return 675000;
> +		default:
> +			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> +		}
> +	}
> +
> +	return dev_priv->cdclk_pll.ref;
> +}
> +
> +/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
> +static int skl_cdclk_decimal(int cdclk)
> +{
> +	return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
> +}
> +
> +static void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv,
> +					int vco)
> +{
> +	bool changed = dev_priv->skl_preferred_vco_freq != vco;
> +
> +	dev_priv->skl_preferred_vco_freq = vco;
> +
> +	if (changed)
> +		intel_update_max_cdclk(dev_priv);
> +}
> +
> +static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
> +{
> +	int min_cdclk = skl_calc_cdclk(0, vco);
> +	u32 val;
> +
> +	WARN_ON(vco != 8100000 && vco != 8640000);
> +
> +	/* select the minimum CDCLK before enabling DPLL 0 */
> +	val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
> +	I915_WRITE(CDCLK_CTL, val);
> +	POSTING_READ(CDCLK_CTL);
> +
> +	/*
> +	 * We always enable DPLL0 with the lowest link rate possible, but
> still
> +	 * taking into account the VCO required to operate the eDP panel at
> the
> +	 * desired frequency. The usual DP link rates operate with a VCO of
> +	 * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
> +	 * The modeset code is responsible for the selection of the exact
> link
> +	 * rate later on, with the constraint of choosing a frequency that
> +	 * works with vco.
> +	 */
> +	val = I915_READ(DPLL_CTRL1);
> +
> +	val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0)
> |
> +		 DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> +	val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
> +	if (vco == 8640000)
> +		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
> +					    SKL_DPLL0);
> +	else
> +		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
> +					    SKL_DPLL0);
> +
> +	I915_WRITE(DPLL_CTRL1, val);
> +	POSTING_READ(DPLL_CTRL1);
> +
> +	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
> +
> +	if (intel_wait_for_register(dev_priv,
> +				    LCPLL1_CTL, LCPLL_PLL_LOCK,
> LCPLL_PLL_LOCK,
> +				    5))
> +		DRM_ERROR("DPLL0 not locked\n");
> +
> +	dev_priv->cdclk_pll.vco = vco;
> +
> +	/* We'll want to keep using the current vco from now on. */
> +	skl_set_preferred_cdclk_vco(dev_priv, vco);
> +}
> +
> +static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
> +{
> +	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
> +	if (intel_wait_for_register(dev_priv,
> +				   LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
> +				   1))
> +		DRM_ERROR("Couldn't disable DPLL0\n");
> +
> +	dev_priv->cdclk_pll.vco = 0;
> +}
> +
> +static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> +			  int cdclk, int vco)
> +{
> +	u32 freq_select, pcu_ack;
> +	int ret;
> +
> +	WARN_ON((cdclk == 24000) != (vco == 0));
> +
> +	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
> +			 cdclk, vco);
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
> +				SKL_CDCLK_PREPARE_FOR_CHANGE,
> +				SKL_CDCLK_READY_FOR_CHANGE,
> +				SKL_CDCLK_READY_FOR_CHANGE, 3);
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +	if (ret) {
> +		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
> +			  ret);
> +		return;
> +	}
> +
> +	/* set CDCLK_CTL */
> +	switch (cdclk) {
> +	case 450000:
> +	case 432000:
> +		freq_select = CDCLK_FREQ_450_432;
> +		pcu_ack = 1;
> +		break;
> +	case 540000:
> +		freq_select = CDCLK_FREQ_540;
> +		pcu_ack = 2;
> +		break;
> +	case 308571:
> +	case 337500:
> +	default:
> +		freq_select = CDCLK_FREQ_337_308;
> +		pcu_ack = 0;
> +		break;
> +	case 617143:
> +	case 675000:
> +		freq_select = CDCLK_FREQ_675_617;
> +		pcu_ack = 3;
> +		break;
> +	}
> +
> +	if (dev_priv->cdclk_pll.vco != 0 &&
> +	    dev_priv->cdclk_pll.vco != vco)
> +		skl_dpll0_disable(dev_priv);
> +
> +	if (dev_priv->cdclk_pll.vco != vco)
> +		skl_dpll0_enable(dev_priv, vco);
> +
> +	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
> +	POSTING_READ(CDCLK_CTL);
> +
> +	/* inform PCU of the change */
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	intel_update_cdclk(dev_priv);
> +}
> +
> +static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	uint32_t cdctl, expected;
> +
> +	/*
> +	 * check if the pre-os initialized the display
> +	 * There is SWF18 scratchpad register defined which is set by the
> +	 * pre-os which can be used by the OS drivers to check the status
> +	 */
> +	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
> +		goto sanitize;
> +
> +	intel_update_cdclk(dev_priv);
> +	/* Is PLL enabled and locked ? */
> +	if (dev_priv->cdclk_pll.vco == 0 ||
> +	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> +		goto sanitize;
> +
> +	/* DPLL okay; verify the cdclock
> +	 *
> +	 * Noticed in some instances that the freq selection is correct but
> +	 * decimal part is programmed wrong from BIOS where pre-os does not
> +	 * enable display. Verify the same as well.
> +	 */
> +	cdctl = I915_READ(CDCLK_CTL);
> +	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
> +		skl_cdclk_decimal(dev_priv->cdclk_freq);
> +	if (cdctl == expected)
> +		/* All well; nothing to sanitize */
> +		return;
> +
> +sanitize:
> +	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> +
> +	/* force cdclk programming */
> +	dev_priv->cdclk_freq = 0;
> +	/* force full PLL disable + enable */
> +	dev_priv->cdclk_pll.vco = -1;
> +}
> +
> +void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> +}
> +
> +void skl_init_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	int cdclk, vco;
> +
> +	skl_sanitize_cdclk(dev_priv);
> +
> +	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
> +		/*
> +		 * Use the current vco as our initial
> +		 * guess as to what the preferred vco is.
> +		 */
> +		if (dev_priv->skl_preferred_vco_freq == 0)
> +			skl_set_preferred_cdclk_vco(dev_priv,
> +						    dev_priv->cdclk_pll.vco);
> +		return;
> +	}
> +
> +	vco = dev_priv->skl_preferred_vco_freq;
> +	if (vco == 0)
> +		vco = 8100000;
> +	cdclk = skl_calc_cdclk(0, vco);
> +
> +	skl_set_cdclk(dev_priv, cdclk, vco);
> +}
> +
> +static int bxt_calc_cdclk(int max_pixclk)
> +{
> +	if (max_pixclk > 576000)
> +		return 624000;
> +	else if (max_pixclk > 384000)
> +		return 576000;
> +	else if (max_pixclk > 288000)
> +		return 384000;
> +	else if (max_pixclk > 144000)
> +		return 288000;
> +	else
> +		return 144000;
> +}
> +
> +static int glk_calc_cdclk(int max_pixclk)
> +{
> +	if (max_pixclk > 2 * 158400)
> +		return 316800;
> +	else if (max_pixclk > 2 * 79200)
> +		return 158400;
> +	else
> +		return 79200;
> +}
> +
> +static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> +{
> +	int ratio;
> +
> +	if (cdclk == dev_priv->cdclk_pll.ref)
> +		return 0;
> +
> +	switch (cdclk) {
> +	default:
> +		MISSING_CASE(cdclk);
> +	case 144000:
> +	case 288000:
> +	case 384000:
> +	case 576000:
> +		ratio = 60;
> +		break;
> +	case 624000:
> +		ratio = 65;
> +		break;
> +	}
> +
> +	return dev_priv->cdclk_pll.ref * ratio;
> +}
> +
> +static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> +{
> +	int ratio;
> +
> +	if (cdclk == dev_priv->cdclk_pll.ref)
> +		return 0;
> +
> +	switch (cdclk) {
> +	default:
> +		MISSING_CASE(cdclk);
> +	case  79200:
> +	case 158400:
> +	case 316800:
> +		ratio = 33;
> +		break;
> +	}
> +
> +	return dev_priv->cdclk_pll.ref * ratio;
> +}
> +
> +static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> +{
> +	u32 val;
> +
> +	dev_priv->cdclk_pll.ref = 19200;
> +	dev_priv->cdclk_pll.vco = 0;
> +
> +	val = I915_READ(BXT_DE_PLL_ENABLE);
> +	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
> +		return;
> +
> +	if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
> +		return;
> +
> +	val = I915_READ(BXT_DE_PLL_CTL);
> +	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
> +		dev_priv->cdclk_pll.ref;
> +}
> +
> +static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	u32 divider;
> +	int div, vco;
> +
> +	bxt_de_pll_update(dev_priv);
> +
> +	vco = dev_priv->cdclk_pll.vco;
> +	if (vco == 0)
> +		return dev_priv->cdclk_pll.ref;
> +
> +	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
> +
> +	switch (divider) {
> +	case BXT_CDCLK_CD2X_DIV_SEL_1:
> +		div = 2;
> +		break;
> +	case BXT_CDCLK_CD2X_DIV_SEL_1_5:
> +		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> +		div = 3;
> +		break;
> +	case BXT_CDCLK_CD2X_DIV_SEL_2:
> +		div = 4;
> +		break;
> +	case BXT_CDCLK_CD2X_DIV_SEL_4:
> +		div = 8;
> +		break;
> +	default:
> +		MISSING_CASE(divider);
> +		return dev_priv->cdclk_pll.ref;
> +	}
> +
> +	return DIV_ROUND_CLOSEST(vco, div);
> +}
> +
> +static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> +{
> +	I915_WRITE(BXT_DE_PLL_ENABLE, 0);
> +
> +	/* Timeout 200us */
> +	if (intel_wait_for_register(dev_priv,
> +				    BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
> +				    1))
> +		DRM_ERROR("timeout waiting for DE PLL unlock\n");
> +
> +	dev_priv->cdclk_pll.vco = 0;
> +}
> +
> +static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
> +{
> +	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
> +	u32 val;
> +
> +	val = I915_READ(BXT_DE_PLL_CTL);
> +	val &= ~BXT_DE_PLL_RATIO_MASK;
> +	val |= BXT_DE_PLL_RATIO(ratio);
> +	I915_WRITE(BXT_DE_PLL_CTL, val);
> +
> +	I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
> +
> +	/* Timeout 200us */
> +	if (intel_wait_for_register(dev_priv,
> +				    BXT_DE_PLL_ENABLE,
> +				    BXT_DE_PLL_LOCK,
> +				    BXT_DE_PLL_LOCK,
> +				    1))
> +		DRM_ERROR("timeout waiting for DE PLL lock\n");
> +
> +	dev_priv->cdclk_pll.vco = vco;
> +}
> +
> +static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> +{
> +	u32 val, divider;
> +	int vco, ret;
> +
> +	if (IS_GEMINILAKE(dev_priv))
> +		vco = glk_de_pll_vco(dev_priv, cdclk);
> +	else
> +		vco = bxt_de_pll_vco(dev_priv, cdclk);
> +
> +	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
> +			 cdclk, vco);
> +
> +	/* cdclk = vco / 2 / div{1,1.5,2,4} */
> +	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
> +	case 8:
> +		divider = BXT_CDCLK_CD2X_DIV_SEL_4;
> +		break;
> +	case 4:
> +		divider = BXT_CDCLK_CD2X_DIV_SEL_2;
> +		break;
> +	case 3:
> +		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> +		divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
> +		break;
> +	case 2:
> +		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> +		break;
> +	default:
> +		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
> +		WARN_ON(vco != 0);
> +
> +		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> +		break;
> +	}
> +
> +	/* Inform power controller of upcoming frequency change */
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> +				      0x80000000);
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	if (ret) {
> +		DRM_ERROR("PCode CDCLK freq change notify failed (err %d,
> freq %d)\n",
> +			  ret, cdclk);
> +		return;
> +	}
> +
> +	if (dev_priv->cdclk_pll.vco != 0 &&
> +	    dev_priv->cdclk_pll.vco != vco)
> +		bxt_de_pll_disable(dev_priv);
> +
> +	if (dev_priv->cdclk_pll.vco != vco)
> +		bxt_de_pll_enable(dev_priv, vco);
> +
> +	val = divider | skl_cdclk_decimal(cdclk);
> +	/*
> +	 * FIXME if only the cd2x divider needs changing, it could be done
> +	 * without shutting off the pipe (if only one pipe is active).
> +	 */
> +	val |= BXT_CDCLK_CD2X_PIPE_NONE;
> +	/*
> +	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
> +	 * enable otherwise.
> +	 */
> +	if (cdclk >= 500000)
> +		val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> +	I915_WRITE(CDCLK_CTL, val);
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> +				      DIV_ROUND_UP(cdclk, 25000));
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	if (ret) {
> +		DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
> +			  ret, cdclk);
> +		return;
> +	}
> +
> +	intel_update_cdclk(dev_priv);
> +}
> +
> +static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	u32 cdctl, expected;
> +
> +	intel_update_cdclk(dev_priv);
> +
> +	if (dev_priv->cdclk_pll.vco == 0 ||
> +	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> +		goto sanitize;
> +
> +	/* DPLL okay; verify the cdclock
> +	 *
> +	 * Some BIOS versions leave an incorrect decimal frequency value and
> +	 * set reserved MBZ bits in CDCLK_CTL at least during exiting from
> S4,
> +	 * so sanitize this register.
> +	 */
> +	cdctl = I915_READ(CDCLK_CTL);
> +	/*
> +	 * Let's ignore the pipe field, since BIOS could have configured the
> +	 * dividers both synching to an active pipe, or asynchronously
> +	 * (PIPE_NONE).
> +	 */
> +	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
> +
> +	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
> +		   skl_cdclk_decimal(dev_priv->cdclk_freq);
> +	/*
> +	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
> +	 * enable otherwise.
> +	 */
> +	if (dev_priv->cdclk_freq >= 500000)
> +		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> +
> +	if (cdctl == expected)
> +		/* All well; nothing to sanitize */
> +		return;
> +
> +sanitize:
> +	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> +
> +	/* force cdclk programming */
> +	dev_priv->cdclk_freq = 0;
> +
> +	/* force full PLL disable + enable */
> +	dev_priv->cdclk_pll.vco = -1;
> +}
> +
> +void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	int cdclk;
> +
> +	bxt_sanitize_cdclk(dev_priv);
> +
> +	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
> +		return;
> +
> +	/*
> +	 * FIXME:
> +	 * - The initial CDCLK needs to be read from VBT.
> +	 *   Need to make this change after VBT has changes for BXT.
> +	 */
> +	if (IS_GEMINILAKE(dev_priv))
> +		cdclk = glk_calc_cdclk(0);
> +	else
> +		cdclk = bxt_calc_cdclk(0);
> +
> +	bxt_set_cdclk(dev_priv, cdclk);
> +}
> +
> +void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
> +}
> +
> +static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state
> *crtc_state,
> +					  int pixel_rate)
> +{
> +	struct drm_i915_private *dev_priv =
> +		to_i915(crtc_state->base.crtc->dev);
> +
> +	/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
> +	if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
> +		pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
> +
> +	/* BSpec says "Do not use DisplayPort with CDCLK less than
> +	 * 432 MHz, audio enabled, port width x4, and link rate
> +	 * HBR2 (5.4 GHz), or else there may be audio corruption or
> +	 * screen corruption."
> +	 */
> +	if (intel_crtc_has_dp_encoder(crtc_state) &&
> +	    crtc_state->has_audio &&
> +	    crtc_state->port_clock >= 540000 &&
> +	    crtc_state->lane_count == 4)
> +		pixel_rate = max(432000, pixel_rate);
> +
> +	return pixel_rate;
> +}
> +
> +/* compute the max rate for new configuration */
> +static int intel_max_pixel_rate(struct drm_atomic_state *state)
> +{
> +	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> +	struct drm_i915_private *dev_priv = to_i915(state->dev);
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *cstate;
> +	struct intel_crtc_state *crtc_state;
> +	unsigned int max_pixel_rate = 0, i;
> +	enum pipe pipe;
> +
> +	memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
> +	       sizeof(intel_state->min_pixclk));
> +
> +	for_each_crtc_in_state(state, crtc, cstate, i) {
> +		int pixel_rate;
> +
> +		crtc_state = to_intel_crtc_state(cstate);
> +		if (!crtc_state->base.enable) {
> +			intel_state->min_pixclk[i] = 0;
> +			continue;
> +		}
> +
> +		pixel_rate = crtc_state->pixel_rate;
> +
> +		if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
> +			pixel_rate =
> +				bdw_adjust_min_pipe_pixel_rate(crtc_state,
> +							       pixel_rate);
> +
> +		intel_state->min_pixclk[i] = pixel_rate;
> +	}
> +
> +	for_each_pipe(dev_priv, pipe)
> +		max_pixel_rate = max(intel_state->min_pixclk[pipe],
> +				     max_pixel_rate);
> +
> +	return max_pixel_rate;
> +}
> +
> +static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> +	struct drm_device *dev = state->dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	int max_pixclk = intel_max_pixel_rate(state);
> +	struct intel_atomic_state *intel_state =
> +		to_intel_atomic_state(state);
> +
> +	intel_state->cdclk = intel_state->dev_cdclk =
> +		vlv_calc_cdclk(dev_priv, max_pixclk);
> +
> +	if (!intel_state->active_crtcs)
> +		intel_state->dev_cdclk = vlv_calc_cdclk(dev_priv, 0);
> +
> +	return 0;
> +}
> +
> +static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> +	struct drm_device *dev = old_state->dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct intel_atomic_state *old_intel_state =
> +		to_intel_atomic_state(old_state);
> +	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +
> +	/*
> +	 * FIXME: We can end up here with all power domains off, yet
> +	 * with a CDCLK frequency other than the minimum. To account
> +	 * for this take the PIPE-A power domain, which covers the HW
> +	 * blocks needed for the following programming. This can be
> +	 * removed once it's guaranteed that we get here either with
> +	 * the minimum CDCLK set, or the required power domains
> +	 * enabled.
> +	 */
> +	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> +
> +	if (IS_CHERRYVIEW(dev_priv))
> +		chv_set_cdclk(dev, req_cdclk);
> +	else
> +		vlv_set_cdclk(dev, req_cdclk);
> +
> +	vlv_program_pfi_credits(dev_priv);
> +
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> +}
> +
> +static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(state->dev);
> +	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> +	int max_pixclk = intel_max_pixel_rate(state);
> +	int cdclk;
> +
> +	/*
> +	 * FIXME should also account for plane ratio
> +	 * once 64bpp pixel formats are supported.
> +	 */
> +	cdclk = bdw_calc_cdclk(max_pixclk);
> +
> +	if (cdclk > dev_priv->max_cdclk_freq) {
> +		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d
> kHz)\n",
> +			      cdclk, dev_priv->max_cdclk_freq);
> +		return -EINVAL;
> +	}
> +
> +	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> +	if (!intel_state->active_crtcs)
> +		intel_state->dev_cdclk = bdw_calc_cdclk(0);
> +
> +	return 0;
> +}
> +
> +static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> +	struct drm_device *dev = old_state->dev;
> +	struct intel_atomic_state *old_intel_state =
> +		to_intel_atomic_state(old_state);
> +	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +
> +	bdw_set_cdclk(dev, req_cdclk);
> +}
> +
> +static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> +	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> +	struct drm_i915_private *dev_priv = to_i915(state->dev);
> +	const int max_pixclk = intel_max_pixel_rate(state);
> +	int vco = intel_state->cdclk_pll_vco;
> +	int cdclk;
> +
> +	/*
> +	 * FIXME should also account for plane ratio
> +	 * once 64bpp pixel formats are supported.
> +	 */
> +	cdclk = skl_calc_cdclk(max_pixclk, vco);
> +
> +	/*
> +	 * FIXME move the cdclk caclulation to
> +	 * compute_config() so we can fail gracegully.
> +	 */
> +	if (cdclk > dev_priv->max_cdclk_freq) {
> +		DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
> +			  cdclk, dev_priv->max_cdclk_freq);
> +		cdclk = dev_priv->max_cdclk_freq;
> +	}
> +
> +	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> +	if (!intel_state->active_crtcs)
> +		intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
> +
> +	return 0;
> +}
> +
> +static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> +	struct intel_atomic_state *intel_state =
> +		to_intel_atomic_state(old_state);
> +	unsigned int req_cdclk = intel_state->dev_cdclk;
> +	unsigned int req_vco = intel_state->cdclk_pll_vco;
> +
> +	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
> +}
> +
> +static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(state->dev);
> +	int max_pixclk = intel_max_pixel_rate(state);
> +	struct intel_atomic_state *intel_state =
> +		to_intel_atomic_state(state);
> +	int cdclk;
> +
> +	if (IS_GEMINILAKE(dev_priv))
> +		cdclk = glk_calc_cdclk(max_pixclk);
> +	else
> +		cdclk = bxt_calc_cdclk(max_pixclk);
> +
> +	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> +
> +	if (!intel_state->active_crtcs) {
> +		if (IS_GEMINILAKE(dev_priv))
> +			cdclk = glk_calc_cdclk(0);
> +		else
> +			cdclk = bxt_calc_cdclk(0);
> +
> +		intel_state->dev_cdclk = cdclk;
> +	}
> +
> +	return 0;
> +}
> +
> +static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> +	struct drm_device *dev = old_state->dev;
> +	struct intel_atomic_state *old_intel_state =
> +		to_intel_atomic_state(old_state);
> +	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +
> +	bxt_set_cdclk(to_i915(dev), req_cdclk);
> +}
> +
> +static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
> +{
> +	int max_cdclk_freq = dev_priv->max_cdclk_freq;
> +
> +	if (IS_GEMINILAKE(dev_priv))
> +		return 2 * max_cdclk_freq;
> +	else if (INTEL_INFO(dev_priv)->gen >= 9 ||
> +		 IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> +		return max_cdclk_freq;
> +	else if (IS_CHERRYVIEW(dev_priv))
> +		return max_cdclk_freq*95/100;
> +	else if (INTEL_INFO(dev_priv)->gen < 4)
> +		return 2*max_cdclk_freq*90/100;
> +	else
> +		return max_cdclk_freq*90/100;
> +}
> +
> +void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> +		u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
> +		int max_cdclk, vco;
> +
> +		vco = dev_priv->skl_preferred_vco_freq;
> +		WARN_ON(vco != 8100000 && vco != 8640000);
> +
> +		/*
> +		 * Use the lower (vco 8640) cdclk values as a
> +		 * first guess. skl_calc_cdclk() will correct it
> +		 * if the preferred vco is 8100 instead.
> +		 */
> +		if (limit == SKL_DFSM_CDCLK_LIMIT_675)
> +			max_cdclk = 617143;
> +		else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
> +			max_cdclk = 540000;
> +		else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
> +			max_cdclk = 432000;
> +		else
> +			max_cdclk = 308571;
> +
> +		dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
> +	} else if (IS_GEMINILAKE(dev_priv)) {
> +		dev_priv->max_cdclk_freq = 316800;
> +	} else if (IS_BROXTON(dev_priv)) {
> +		dev_priv->max_cdclk_freq = 624000;
> +	} else if (IS_BROADWELL(dev_priv))  {
> +		/*
> +		 * FIXME with extra cooling we can allow
> +		 * 540 MHz for ULX and 675 Mhz for ULT.
> +		 * How can we know if extra cooling is
> +		 * available? PCI ID, VTB, something else?
> +		 */
> +		if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> +			dev_priv->max_cdclk_freq = 450000;
> +		else if (IS_BDW_ULX(dev_priv))
> +			dev_priv->max_cdclk_freq = 450000;
> +		else if (IS_BDW_ULT(dev_priv))
> +			dev_priv->max_cdclk_freq = 540000;
> +		else
> +			dev_priv->max_cdclk_freq = 675000;
> +	} else if (IS_CHERRYVIEW(dev_priv)) {
> +		dev_priv->max_cdclk_freq = 320000;
> +	} else if (IS_VALLEYVIEW(dev_priv)) {
> +		dev_priv->max_cdclk_freq = 400000;
> +	} else {
> +		/* otherwise assume cdclk is fixed */
> +		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
> +	}
> +
> +	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
> +
> +	DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
> +			 dev_priv->max_cdclk_freq);
> +
> +	DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
> +			 dev_priv->max_dotclk_freq);
> +}
> +
> +void intel_update_cdclk(struct drm_i915_private *dev_priv)
> +{
> +	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
> +
> +	if (INTEL_GEN(dev_priv) >= 9)
> +		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz,
> ref: %d kHz\n",
> +				 dev_priv->cdclk_freq, dev_priv-
> >cdclk_pll.vco,
> +				 dev_priv->cdclk_pll.ref);
> +	else
> +		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
> +				 dev_priv->cdclk_freq);
> +
> +	/*
> +	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
> +	 * Programmng [sic] note: bit[9:2] should be programmed to the number
> +	 * of cdclk that generates 4MHz reference clock freq which is used to
> +	 * generate GMBus clock. This will vary with the cdclk freq.
> +	 */
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		I915_WRITE(GMBUSFREQ_VLV,
> +			   DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
> +}
> +
> +static int pch_rawclk(struct drm_i915_private *dev_priv)
> +{
> +	return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
> +}
> +
> +static int vlv_hrawclk(struct drm_i915_private *dev_priv)
> +{
> +	/* RAWCLK_FREQ_VLV register updated from power well code */
> +	return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
> +				      CCK_DISPLAY_REF_CLOCK_CONTROL);
> +}
> +
> +static int g4x_hrawclk(struct drm_i915_private *dev_priv)
> +{
> +	uint32_t clkcfg;
> +
> +	/* hrawclock is 1/4 the FSB frequency */
> +	clkcfg = I915_READ(CLKCFG);
> +	switch (clkcfg & CLKCFG_FSB_MASK) {
> +	case CLKCFG_FSB_400:
> +		return 100000;
> +	case CLKCFG_FSB_533:
> +		return 133333;
> +	case CLKCFG_FSB_667:
> +		return 166667;
> +	case CLKCFG_FSB_800:
> +		return 200000;
> +	case CLKCFG_FSB_1067:
> +		return 266667;
> +	case CLKCFG_FSB_1333:
> +		return 333333;
> +	/* these two are just a guess; one of them might be right */
> +	case CLKCFG_FSB_1600:
> +	case CLKCFG_FSB_1600_ALT:
> +		return 400000;
> +	default:
> +		return 133333;
> +	}
> +}
> +
> +void intel_update_rawclk(struct drm_i915_private *dev_priv)
> +{
> +	if (HAS_PCH_SPLIT(dev_priv))
> +		dev_priv->rawclk_freq = pch_rawclk(dev_priv);
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		dev_priv->rawclk_freq = vlv_hrawclk(dev_priv);
> +	else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
> +		dev_priv->rawclk_freq = g4x_hrawclk(dev_priv);
> +	else
> +		/* no rawclk on other platforms, or no need to know it */
> +		return;
> +
> +	DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
> +}
> +
> +void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
> +{
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +		dev_priv->display.modeset_commit_cdclk =
> +			vlv_modeset_commit_cdclk;
> +		dev_priv->display.modeset_calc_cdclk =
> +			vlv_modeset_calc_cdclk;
> +	} else if (IS_BROADWELL(dev_priv)) {
> +		dev_priv->display.modeset_commit_cdclk =
> +			bdw_modeset_commit_cdclk;
> +		dev_priv->display.modeset_calc_cdclk =
> +			bdw_modeset_calc_cdclk;
> +	} else if (IS_GEN9_LP(dev_priv)) {
> +		dev_priv->display.modeset_commit_cdclk =
> +			bxt_modeset_commit_cdclk;
> +		dev_priv->display.modeset_calc_cdclk =
> +			bxt_modeset_calc_cdclk;
> +	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> +		dev_priv->display.modeset_commit_cdclk =
> +			skl_modeset_commit_cdclk;
> +		dev_priv->display.modeset_calc_cdclk =
> +			skl_modeset_calc_cdclk;
> +	}
> +
> +	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> +		dev_priv->display.get_cdclk = skl_get_cdclk;
> +	else if (IS_GEN9_LP(dev_priv))
> +		dev_priv->display.get_cdclk = bxt_get_cdclk;
> +	else if (IS_BROADWELL(dev_priv))
> +		dev_priv->display.get_cdclk = bdw_get_cdclk;
> +	else if (IS_HASWELL(dev_priv))
> +		dev_priv->display.get_cdclk = hsw_get_cdclk;
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		dev_priv->display.get_cdclk = vlv_get_cdclk;
> +	else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> +	else if (IS_GEN5(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
> +	else if (IS_GM45(dev_priv))
> +		dev_priv->display.get_cdclk = gm45_get_cdclk;
> +	else if (IS_G4X(dev_priv))
> +		dev_priv->display.get_cdclk = g33_get_cdclk;
> +	else if (IS_I965GM(dev_priv))
> +		dev_priv->display.get_cdclk = i965gm_get_cdclk;
> +	else if (IS_I965G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> +	else if (IS_PINEVIEW(dev_priv))
> +		dev_priv->display.get_cdclk = pnv_get_cdclk;
> +	else if (IS_G33(dev_priv))
> +		dev_priv->display.get_cdclk = g33_get_cdclk;
> +	else if (IS_I945GM(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> +	else if (IS_I945G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> +	else if (IS_I915GM(dev_priv))
> +		dev_priv->display.get_cdclk = i915gm_get_cdclk;
> +	else if (IS_I915G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
> +	else if (IS_I865G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
> +	else if (IS_I85X(dev_priv))
> +		dev_priv->display.get_cdclk = i85x_get_cdclk;
> +	else if (IS_I845G(dev_priv))
> +		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> +	else { /* 830 */
> +		WARN(!IS_I830(dev_priv),
> +		     "Unknown platform. Assuming 133 MHz CDCLK\n");
> +		dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
> +	}
> +}
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 29f91e799272..519e5d663c5f 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -123,9 +123,6 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc,
> bool force);
>  static void ironlake_pfit_enable(struct intel_crtc *crtc);
>  static void intel_modeset_setup_hw_state(struct drm_device *dev);
>  static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
> -static int intel_max_pixel_rate(struct drm_atomic_state *state);
> -static int glk_calc_cdclk(int max_pixclk);
> -static int bxt_calc_cdclk(int max_pixclk);
>  
>  struct intel_limit {
>  	struct {
> @@ -171,8 +168,8 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
>  	return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
>  }
>  
> -static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> -				  const char *name, u32 reg)
> +int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> +			   const char *name, u32 reg)
>  {
>  	if (dev_priv->hpll_freq == 0)
>  		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
> @@ -181,63 +178,6 @@ static int vlv_get_cck_clock_hpll(struct drm_i915_private
> *dev_priv,
>  				 dev_priv->hpll_freq);
>  }
>  
> -static int
> -intel_pch_rawclk(struct drm_i915_private *dev_priv)
> -{
> -	return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
> -}
> -
> -static int
> -intel_vlv_hrawclk(struct drm_i915_private *dev_priv)
> -{
> -	/* RAWCLK_FREQ_VLV register updated from power well code */
> -	return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
> -				      CCK_DISPLAY_REF_CLOCK_CONTROL);
> -}
> -
> -static int
> -intel_g4x_hrawclk(struct drm_i915_private *dev_priv)
> -{
> -	uint32_t clkcfg;
> -
> -	/* hrawclock is 1/4 the FSB frequency */
> -	clkcfg = I915_READ(CLKCFG);
> -	switch (clkcfg & CLKCFG_FSB_MASK) {
> -	case CLKCFG_FSB_400:
> -		return 100000;
> -	case CLKCFG_FSB_533:
> -		return 133333;
> -	case CLKCFG_FSB_667:
> -		return 166667;
> -	case CLKCFG_FSB_800:
> -		return 200000;
> -	case CLKCFG_FSB_1067:
> -		return 266667;
> -	case CLKCFG_FSB_1333:
> -		return 333333;
> -	/* these two are just a guess; one of them might be right */
> -	case CLKCFG_FSB_1600:
> -	case CLKCFG_FSB_1600_ALT:
> -		return 400000;
> -	default:
> -		return 133333;
> -	}
> -}
> -
> -void intel_update_rawclk(struct drm_i915_private *dev_priv)
> -{
> -	if (HAS_PCH_SPLIT(dev_priv))
> -		dev_priv->rawclk_freq = intel_pch_rawclk(dev_priv);
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		dev_priv->rawclk_freq = intel_vlv_hrawclk(dev_priv);
> -	else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
> -		dev_priv->rawclk_freq = intel_g4x_hrawclk(dev_priv);
> -	else
> -		return; /* no rawclk on other platforms, or no need to know
> it */
> -
> -	DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
> -}
> -
>  static void intel_update_czclk(struct drm_i915_private *dev_priv)
>  {
>  	if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
> @@ -5791,1092 +5731,210 @@ static void modeset_put_power_domains(struct
> drm_i915_private *dev_priv,
>  		intel_display_power_put(dev_priv, domain);
>  }
>  
> -static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
> +static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> +				   struct drm_atomic_state *old_state)
>  {
> -	int max_cdclk_freq = dev_priv->max_cdclk_freq;
> +	struct drm_crtc *crtc = pipe_config->base.crtc;
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	int pipe = intel_crtc->pipe;
>  
> -	if (IS_GEMINILAKE(dev_priv))
> -		return 2 * max_cdclk_freq;
> -	else if (INTEL_INFO(dev_priv)->gen >= 9 ||
> -		 IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> -		return max_cdclk_freq;
> -	else if (IS_CHERRYVIEW(dev_priv))
> -		return max_cdclk_freq*95/100;
> -	else if (INTEL_INFO(dev_priv)->gen < 4)
> -		return 2*max_cdclk_freq*90/100;
> -	else
> -		return max_cdclk_freq*90/100;
> -}
> +	if (WARN_ON(intel_crtc->active))
> +		return;
>  
> -static int skl_calc_cdclk(int max_pixclk, int vco);
> +	if (intel_crtc_has_dp_encoder(intel_crtc->config))
> +		intel_dp_set_m_n(intel_crtc, M1_N1);
>  
> -static void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> -		u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
> -		int max_cdclk, vco;
> +	intel_set_pipe_timings(intel_crtc);
> +	intel_set_pipe_src_size(intel_crtc);
>  
> -		vco = dev_priv->skl_preferred_vco_freq;
> -		WARN_ON(vco != 8100000 && vco != 8640000);
> +	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> +		struct drm_i915_private *dev_priv = to_i915(dev);
>  
> -		/*
> -		 * Use the lower (vco 8640) cdclk values as a
> -		 * first guess. skl_calc_cdclk() will correct it
> -		 * if the preferred vco is 8100 instead.
> -		 */
> -		if (limit == SKL_DFSM_CDCLK_LIMIT_675)
> -			max_cdclk = 617143;
> -		else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
> -			max_cdclk = 540000;
> -		else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
> -			max_cdclk = 432000;
> -		else
> -			max_cdclk = 308571;
> -
> -		dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
> -	} else if (IS_GEMINILAKE(dev_priv)) {
> -		dev_priv->max_cdclk_freq = 316800;
> -	} else if (IS_BROXTON(dev_priv)) {
> -		dev_priv->max_cdclk_freq = 624000;
> -	} else if (IS_BROADWELL(dev_priv))  {
> -		/*
> -		 * FIXME with extra cooling we can allow
> -		 * 540 MHz for ULX and 675 Mhz for ULT.
> -		 * How can we know if extra cooling is
> -		 * available? PCI ID, VTB, something else?
> -		 */
> -		if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> -			dev_priv->max_cdclk_freq = 450000;
> -		else if (IS_BDW_ULX(dev_priv))
> -			dev_priv->max_cdclk_freq = 450000;
> -		else if (IS_BDW_ULT(dev_priv))
> -			dev_priv->max_cdclk_freq = 540000;
> -		else
> -			dev_priv->max_cdclk_freq = 675000;
> -	} else if (IS_CHERRYVIEW(dev_priv)) {
> -		dev_priv->max_cdclk_freq = 320000;
> -	} else if (IS_VALLEYVIEW(dev_priv)) {
> -		dev_priv->max_cdclk_freq = 400000;
> -	} else {
> -		/* otherwise assume cdclk is fixed */
> -		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
> +		I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
> +		I915_WRITE(CHV_CANVAS(pipe), 0);
>  	}
>  
> -	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
> -
> -	DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
> -			 dev_priv->max_cdclk_freq);
> -
> -	DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
> -			 dev_priv->max_dotclk_freq);
> -}
> -
> -static void intel_update_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
> -
> -	if (INTEL_GEN(dev_priv) >= 9)
> -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz,
> ref: %d kHz\n",
> -				 dev_priv->cdclk_freq, dev_priv-
> >cdclk_pll.vco,
> -				 dev_priv->cdclk_pll.ref);
> -	else
> -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
> -				 dev_priv->cdclk_freq);
> -
> -	/*
> -	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
> -	 * Programmng [sic] note: bit[9:2] should be programmed to the number
> -	 * of cdclk that generates 4MHz reference clock freq which is used to
> -	 * generate GMBus clock. This will vary with the cdclk freq.
> -	 */
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq,
> 1000));
> -}
> +	i9xx_set_pipeconf(intel_crtc);
>  
> -/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
> -static int skl_cdclk_decimal(int cdclk)
> -{
> -	return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
> -}
> +	intel_crtc->active = true;
>  
> -static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> -{
> -	int ratio;
> +	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
>  
> -	if (cdclk == dev_priv->cdclk_pll.ref)
> -		return 0;
> +	intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
>  
> -	switch (cdclk) {
> -	default:
> -		MISSING_CASE(cdclk);
> -	case 144000:
> -	case 288000:
> -	case 384000:
> -	case 576000:
> -		ratio = 60;
> -		break;
> -	case 624000:
> -		ratio = 65;
> -		break;
> +	if (IS_CHERRYVIEW(dev_priv)) {
> +		chv_prepare_pll(intel_crtc, intel_crtc->config);
> +		chv_enable_pll(intel_crtc, intel_crtc->config);
> +	} else {
> +		vlv_prepare_pll(intel_crtc, intel_crtc->config);
> +		vlv_enable_pll(intel_crtc, intel_crtc->config);
>  	}
>  
> -	return dev_priv->cdclk_pll.ref * ratio;
> -}
> +	intel_encoders_pre_enable(crtc, pipe_config, old_state);
>  
> -static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> -{
> -	int ratio;
> +	i9xx_pfit_enable(intel_crtc);
>  
> -	if (cdclk == dev_priv->cdclk_pll.ref)
> -		return 0;
> +	intel_color_load_luts(&pipe_config->base);
>  
> -	switch (cdclk) {
> -	default:
> -		MISSING_CASE(cdclk);
> -	case  79200:
> -	case 158400:
> -	case 316800:
> -		ratio = 33;
> -		break;
> -	}
> +	intel_update_watermarks(intel_crtc);
> +	intel_enable_pipe(intel_crtc);
> +
> +	assert_vblank_disabled(crtc);
> +	drm_crtc_vblank_on(crtc);
>  
> -	return dev_priv->cdclk_pll.ref * ratio;
> +	intel_encoders_enable(crtc, pipe_config, old_state);
>  }
>  
> -static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> +static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
>  {
> -	I915_WRITE(BXT_DE_PLL_ENABLE, 0);
> -
> -	/* Timeout 200us */
> -	if (intel_wait_for_register(dev_priv,
> -				    BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
> -				    1))
> -		DRM_ERROR("timeout waiting for DE PLL unlock\n");
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
>  
> -	dev_priv->cdclk_pll.vco = 0;
> +	I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
> +	I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
>  }
>  
> -static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
> +static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
> +			     struct drm_atomic_state *old_state)
>  {
> -	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
> -	u32 val;
> +	struct drm_crtc *crtc = pipe_config->base.crtc;
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	enum pipe pipe = intel_crtc->pipe;
>  
> -	val = I915_READ(BXT_DE_PLL_CTL);
> -	val &= ~BXT_DE_PLL_RATIO_MASK;
> -	val |= BXT_DE_PLL_RATIO(ratio);
> -	I915_WRITE(BXT_DE_PLL_CTL, val);
> +	if (WARN_ON(intel_crtc->active))
> +		return;
>  
> -	I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
> +	i9xx_set_pll_dividers(intel_crtc);
>  
> -	/* Timeout 200us */
> -	if (intel_wait_for_register(dev_priv,
> -				    BXT_DE_PLL_ENABLE,
> -				    BXT_DE_PLL_LOCK,
> -				    BXT_DE_PLL_LOCK,
> -				    1))
> -		DRM_ERROR("timeout waiting for DE PLL lock\n");
> +	if (intel_crtc_has_dp_encoder(intel_crtc->config))
> +		intel_dp_set_m_n(intel_crtc, M1_N1);
>  
> -	dev_priv->cdclk_pll.vco = vco;
> -}
> +	intel_set_pipe_timings(intel_crtc);
> +	intel_set_pipe_src_size(intel_crtc);
>  
> -static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> -{
> -	u32 val, divider;
> -	int vco, ret;
> +	i9xx_set_pipeconf(intel_crtc);
>  
> -	if (IS_GEMINILAKE(dev_priv))
> -		vco = glk_de_pll_vco(dev_priv, cdclk);
> -	else
> -		vco = bxt_de_pll_vco(dev_priv, cdclk);
> +	intel_crtc->active = true;
>  
> -	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk,
> vco);
> +	if (!IS_GEN2(dev_priv))
> +		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
>  
> -	/* cdclk = vco / 2 / div{1,1.5,2,4} */
> -	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
> -	case 8:
> -		divider = BXT_CDCLK_CD2X_DIV_SEL_4;
> -		break;
> -	case 4:
> -		divider = BXT_CDCLK_CD2X_DIV_SEL_2;
> -		break;
> -	case 3:
> -		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> -		divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
> -		break;
> -	case 2:
> -		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> -		break;
> -	default:
> -		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
> -		WARN_ON(vco != 0);
> +	intel_encoders_pre_enable(crtc, pipe_config, old_state);
>  
> -		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> -		break;
> -	}
> +	i9xx_enable_pll(intel_crtc);
>  
> -	/* Inform power controller of upcoming frequency change */
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> -				      0x80000000);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> +	i9xx_pfit_enable(intel_crtc);
>  
> -	if (ret) {
> -		DRM_ERROR("PCode CDCLK freq change notify failed (err %d,
> freq %d)\n",
> -			  ret, cdclk);
> -		return;
> -	}
> +	intel_color_load_luts(&pipe_config->base);
>  
> -	if (dev_priv->cdclk_pll.vco != 0 &&
> -	    dev_priv->cdclk_pll.vco != vco)
> -		bxt_de_pll_disable(dev_priv);
> +	intel_update_watermarks(intel_crtc);
> +	intel_enable_pipe(intel_crtc);
>  
> -	if (dev_priv->cdclk_pll.vco != vco)
> -		bxt_de_pll_enable(dev_priv, vco);
> +	assert_vblank_disabled(crtc);
> +	drm_crtc_vblank_on(crtc);
>  
> -	val = divider | skl_cdclk_decimal(cdclk);
> -	/*
> -	 * FIXME if only the cd2x divider needs changing, it could be done
> -	 * without shutting off the pipe (if only one pipe is active).
> -	 */
> -	val |= BXT_CDCLK_CD2X_PIPE_NONE;
> -	/*
> -	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
> -	 * enable otherwise.
> -	 */
> -	if (cdclk >= 500000)
> -		val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> -	I915_WRITE(CDCLK_CTL, val);
> +	intel_encoders_enable(crtc, pipe_config, old_state);
> +}
>  
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> -				      DIV_ROUND_UP(cdclk, 25000));
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> +static void i9xx_pfit_disable(struct intel_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
>  
> -	if (ret) {
> -		DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
> -			  ret, cdclk);
> +	if (!crtc->config->gmch_pfit.control)
>  		return;
> -	}
>  
> -	intel_update_cdclk(dev_priv);
> +	assert_pipe_disabled(dev_priv, crtc->pipe);
> +
> +	DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
> +			 I915_READ(PFIT_CONTROL));
> +	I915_WRITE(PFIT_CONTROL, 0);
>  }
>  
> -static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> +static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
> +			      struct drm_atomic_state *old_state)
>  {
> -	u32 cdctl, expected;
> -
> -	intel_update_cdclk(dev_priv);
> -
> -	if (dev_priv->cdclk_pll.vco == 0 ||
> -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> -		goto sanitize;
> -
> -	/* DPLL okay; verify the cdclock
> -	 *
> -	 * Some BIOS versions leave an incorrect decimal frequency value and
> -	 * set reserved MBZ bits in CDCLK_CTL at least during exiting from
> S4,
> -	 * so sanitize this register.
> -	 */
> -	cdctl = I915_READ(CDCLK_CTL);
> -	/*
> -	 * Let's ignore the pipe field, since BIOS could have configured the
> -	 * dividers both synching to an active pipe, or asynchronously
> -	 * (PIPE_NONE).
> -	 */
> -	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
> +	struct drm_crtc *crtc = old_crtc_state->base.crtc;
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	int pipe = intel_crtc->pipe;
>  
> -	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
> -		   skl_cdclk_decimal(dev_priv->cdclk_freq);
>  	/*
> -	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
> -	 * enable otherwise.
> +	 * On gen2 planes are double buffered but the pipe isn't, so we must
> +	 * wait for planes to fully turn off before disabling the pipe.
>  	 */
> -	if (dev_priv->cdclk_freq >= 500000)
> -		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> -
> -	if (cdctl == expected)
> -		/* All well; nothing to sanitize */
> -		return;
> +	if (IS_GEN2(dev_priv))
> +		intel_wait_for_vblank(dev_priv, pipe);
>  
> -sanitize:
> -	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> +	intel_encoders_disable(crtc, old_crtc_state, old_state);
>  
> -	/* force cdclk programming */
> -	dev_priv->cdclk_freq = 0;
> +	drm_crtc_vblank_off(crtc);
> +	assert_vblank_disabled(crtc);
>  
> -	/* force full PLL disable + enable */
> -	dev_priv->cdclk_pll.vco = -1;
> -}
> +	intel_disable_pipe(intel_crtc);
>  
> -void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	int cdclk;
> +	i9xx_pfit_disable(intel_crtc);
>  
> -	bxt_sanitize_cdclk(dev_priv);
> +	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
>  
> -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
> -		return;
> +	if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
> +		if (IS_CHERRYVIEW(dev_priv))
> +			chv_disable_pll(dev_priv, pipe);
> +		else if (IS_VALLEYVIEW(dev_priv))
> +			vlv_disable_pll(dev_priv, pipe);
> +		else
> +			i9xx_disable_pll(intel_crtc);
> +	}
>  
> -	/*
> -	 * FIXME:
> -	 * - The initial CDCLK needs to be read from VBT.
> -	 *   Need to make this change after VBT has changes for BXT.
> -	 */
> -	if (IS_GEMINILAKE(dev_priv))
> -		cdclk = glk_calc_cdclk(0);
> -	else
> -		cdclk = bxt_calc_cdclk(0);
> +	intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
>  
> -	bxt_set_cdclk(dev_priv, cdclk);
> +	if (!IS_GEN2(dev_priv))
> +		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
>  }
>  
> -void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
> +static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
>  {
> -	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
> -}
> +	struct intel_encoder *encoder;
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> +	enum intel_display_power_domain domain;
> +	unsigned long domains;
> +	struct drm_atomic_state *state;
> +	struct intel_crtc_state *crtc_state;
> +	int ret;
>  
> -static int skl_calc_cdclk(int max_pixclk, int vco)
> -{
> -	if (vco == 8640000) {
> -		if (max_pixclk > 540000)
> -			return 617143;
> -		else if (max_pixclk > 432000)
> -			return 540000;
> -		else if (max_pixclk > 308571)
> -			return 432000;
> -		else
> -			return 308571;
> -	} else {
> -		if (max_pixclk > 540000)
> -			return 675000;
> -		else if (max_pixclk > 450000)
> -			return 540000;
> -		else if (max_pixclk > 337500)
> -			return 450000;
> -		else
> -			return 337500;
> -	}
> -}
> +	if (!intel_crtc->active)
> +		return;
>  
> -static void
> -skl_dpll0_update(struct drm_i915_private *dev_priv)
> -{
> -	u32 val;
> +	if (to_intel_plane_state(crtc->primary->state)->base.visible) {
> +		WARN_ON(intel_crtc->flip_work);
>  
> -	dev_priv->cdclk_pll.ref = 24000;
> -	dev_priv->cdclk_pll.vco = 0;
> +		intel_pre_disable_primary_noatomic(crtc);
>  
> -	val = I915_READ(LCPLL1_CTL);
> -	if ((val & LCPLL_PLL_ENABLE) == 0)
> -		return;
> +		intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc-
> >primary));
> +		to_intel_plane_state(crtc->primary->state)->base.visible =
> false;
> +	}
>  
> -	if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
> -		return;
> +	state = drm_atomic_state_alloc(crtc->dev);
> +	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
>  
> -	val = I915_READ(DPLL_CTRL1);
> +	/* Everything's already locked, -EDEADLK can't happen. */
> +	crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
> +	ret = drm_atomic_add_affected_connectors(state, crtc);
>  
> -	if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
> -			    DPLL_CTRL1_SSC(SKL_DPLL0) |
> -			    DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
> -		    DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
> -		return;
> +	WARN_ON(IS_ERR(crtc_state) || ret);
>  
> -	switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
> -	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
> -	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
> -	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
> -	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
> -		dev_priv->cdclk_pll.vco = 8100000;
> -		break;
> -	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
> -	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
> -		dev_priv->cdclk_pll.vco = 8640000;
> -		break;
> -	default:
> -		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> -		break;
> -	}
> -}
> +	dev_priv->display.crtc_disable(crtc_state, state);
>  
> -void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
> -{
> -	bool changed = dev_priv->skl_preferred_vco_freq != vco;
> +	drm_atomic_state_put(state);
>  
> -	dev_priv->skl_preferred_vco_freq = vco;
> -
> -	if (changed)
> -		intel_update_max_cdclk(dev_priv);
> -}
> -
> -static void
> -skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
> -{
> -	int min_cdclk = skl_calc_cdclk(0, vco);
> -	u32 val;
> -
> -	WARN_ON(vco != 8100000 && vco != 8640000);
> -
> -	/* select the minimum CDCLK before enabling DPLL 0 */
> -	val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
> -	I915_WRITE(CDCLK_CTL, val);
> -	POSTING_READ(CDCLK_CTL);
> -
> -	/*
> -	 * We always enable DPLL0 with the lowest link rate possible, but
> still
> -	 * taking into account the VCO required to operate the eDP panel at
> the
> -	 * desired frequency. The usual DP link rates operate with a VCO of
> -	 * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
> -	 * The modeset code is responsible for the selection of the exact
> link
> -	 * rate later on, with the constraint of choosing a frequency that
> -	 * works with vco.
> -	 */
> -	val = I915_READ(DPLL_CTRL1);
> -
> -	val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0)
> |
> -		 DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> -	val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
> -	if (vco == 8640000)
> -		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
> -					    SKL_DPLL0);
> -	else
> -		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
> -					    SKL_DPLL0);
> -
> -	I915_WRITE(DPLL_CTRL1, val);
> -	POSTING_READ(DPLL_CTRL1);
> -
> -	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
> -
> -	if (intel_wait_for_register(dev_priv,
> -				    LCPLL1_CTL, LCPLL_PLL_LOCK,
> LCPLL_PLL_LOCK,
> -				    5))
> -		DRM_ERROR("DPLL0 not locked\n");
> -
> -	dev_priv->cdclk_pll.vco = vco;
> -
> -	/* We'll want to keep using the current vco from now on. */
> -	skl_set_preferred_cdclk_vco(dev_priv, vco);
> -}
> -
> -static void
> -skl_dpll0_disable(struct drm_i915_private *dev_priv)
> -{
> -	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
> -	if (intel_wait_for_register(dev_priv,
> -				   LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
> -				   1))
> -		DRM_ERROR("Couldn't disable DPLL0\n");
> -
> -	dev_priv->cdclk_pll.vco = 0;
> -}
> -
> -static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int
> vco)
> -{
> -	u32 freq_select, pcu_ack;
> -	int ret;
> -
> -	WARN_ON((cdclk == 24000) != (vco == 0));
> -
> -	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk,
> vco);
> -
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
> -				SKL_CDCLK_PREPARE_FOR_CHANGE,
> -				SKL_CDCLK_READY_FOR_CHANGE,
> -				SKL_CDCLK_READY_FOR_CHANGE, 3);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> -	if (ret) {
> -		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
> -			  ret);
> -		return;
> -	}
> -
> -	/* set CDCLK_CTL */
> -	switch (cdclk) {
> -	case 450000:
> -	case 432000:
> -		freq_select = CDCLK_FREQ_450_432;
> -		pcu_ack = 1;
> -		break;
> -	case 540000:
> -		freq_select = CDCLK_FREQ_540;
> -		pcu_ack = 2;
> -		break;
> -	case 308571:
> -	case 337500:
> -	default:
> -		freq_select = CDCLK_FREQ_337_308;
> -		pcu_ack = 0;
> -		break;
> -	case 617143:
> -	case 675000:
> -		freq_select = CDCLK_FREQ_675_617;
> -		pcu_ack = 3;
> -		break;
> -	}
> -
> -	if (dev_priv->cdclk_pll.vco != 0 &&
> -	    dev_priv->cdclk_pll.vco != vco)
> -		skl_dpll0_disable(dev_priv);
> -
> -	if (dev_priv->cdclk_pll.vco != vco)
> -		skl_dpll0_enable(dev_priv, vco);
> -
> -	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
> -	POSTING_READ(CDCLK_CTL);
> -
> -	/* inform PCU of the change */
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> -
> -	intel_update_cdclk(dev_priv);
> -}
> -
> -static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
> -
> -void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> -}
> -
> -void skl_init_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	int cdclk, vco;
> -
> -	skl_sanitize_cdclk(dev_priv);
> -
> -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
> -		/*
> -		 * Use the current vco as our initial
> -		 * guess as to what the preferred vco is.
> -		 */
> -		if (dev_priv->skl_preferred_vco_freq == 0)
> -			skl_set_preferred_cdclk_vco(dev_priv,
> -						    dev_priv->cdclk_pll.vco);
> -		return;
> -	}
> -
> -	vco = dev_priv->skl_preferred_vco_freq;
> -	if (vco == 0)
> -		vco = 8100000;
> -	cdclk = skl_calc_cdclk(0, vco);
> -
> -	skl_set_cdclk(dev_priv, cdclk, vco);
> -}
> -
> -static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	uint32_t cdctl, expected;
> -
> -	/*
> -	 * check if the pre-os intialized the display
> -	 * There is SWF18 scratchpad register defined which is set by the
> -	 * pre-os which can be used by the OS drivers to check the status
> -	 */
> -	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
> -		goto sanitize;
> -
> -	intel_update_cdclk(dev_priv);
> -	/* Is PLL enabled and locked ? */
> -	if (dev_priv->cdclk_pll.vco == 0 ||
> -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> -		goto sanitize;
> -
> -	/* DPLL okay; verify the cdclock
> -	 *
> -	 * Noticed in some instances that the freq selection is correct but
> -	 * decimal part is programmed wrong from BIOS where pre-os does not
> -	 * enable display. Verify the same as well.
> -	 */
> -	cdctl = I915_READ(CDCLK_CTL);
> -	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
> -		skl_cdclk_decimal(dev_priv->cdclk_freq);
> -	if (cdctl == expected)
> -		/* All well; nothing to sanitize */
> -		return;
> -
> -sanitize:
> -	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> -
> -	/* force cdclk programming */
> -	dev_priv->cdclk_freq = 0;
> -	/* force full PLL disable + enable */
> -	dev_priv->cdclk_pll.vco = -1;
> -}
> -
> -/* Adjust CDclk dividers to allow high res or save power if possible */
> -static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	u32 val, cmd;
> -
> -	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv-
> >cdclk_freq);
> -
> -	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
> -		cmd = 2;
> -	else if (cdclk == 266667)
> -		cmd = 1;
> -	else
> -		cmd = 0;
> -
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> -	val &= ~DSPFREQGUAR_MASK;
> -	val |= (cmd << DSPFREQGUAR_SHIFT);
> -	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> -	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> -		      DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
> -		     50)) {
> -		DRM_ERROR("timed out waiting for CDclk change\n");
> -	}
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> -
> -	mutex_lock(&dev_priv->sb_lock);
> -
> -	if (cdclk == 400000) {
> -		u32 divider;
> -
> -		divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk)
> - 1;
> -
> -		/* adjust cdclk divider */
> -		val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
> -		val &= ~CCK_FREQUENCY_VALUES;
> -		val |= divider;
> -		vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
> -
> -		if (wait_for((vlv_cck_read(dev_priv,
> CCK_DISPLAY_CLOCK_CONTROL) &
> -			      CCK_FREQUENCY_STATUS) == (divider <<
> CCK_FREQUENCY_STATUS_SHIFT),
> -			     50))
> -			DRM_ERROR("timed out waiting for CDclk change\n");
> -	}
> -
> -	/* adjust self-refresh exit latency value */
> -	val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
> -	val &= ~0x7f;
> -
> -	/*
> -	 * For high bandwidth configs, we set a higher latency in the bunit
> -	 * so that the core display fetch happens in time to avoid underruns.
> -	 */
> -	if (cdclk == 400000)
> -		val |= 4500 / 250; /* 4.5 usec */
> -	else
> -		val |= 3000 / 250; /* 3.0 usec */
> -	vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
> -
> -	mutex_unlock(&dev_priv->sb_lock);
> -
> -	intel_update_cdclk(dev_priv);
> -}
> -
> -static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	u32 val, cmd;
> -
> -	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv-
> >cdclk_freq);
> -
> -	switch (cdclk) {
> -	case 333333:
> -	case 320000:
> -	case 266667:
> -	case 200000:
> -		break;
> -	default:
> -		MISSING_CASE(cdclk);
> -		return;
> -	}
> -
> -	/*
> -	 * Specs are full of misinformation, but testing on actual
> -	 * hardware has shown that we just need to write the desired
> -	 * CCK divider into the Punit register.
> -	 */
> -	cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
> -
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> -	val &= ~DSPFREQGUAR_MASK_CHV;
> -	val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
> -	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> -	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> -		      DSPFREQSTAT_MASK_CHV) == (cmd <<
> DSPFREQSTAT_SHIFT_CHV),
> -		     50)) {
> -		DRM_ERROR("timed out waiting for CDclk change\n");
> -	}
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> -
> -	intel_update_cdclk(dev_priv);
> -}
> -
> -static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
> -				 int max_pixclk)
> -{
> -	int freq_320 = (dev_priv->hpll_freq <<  1) % 320000 != 0 ? 333333 :
> 320000;
> -	int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
> -
> -	/*
> -	 * Really only a few cases to deal with, as only 4 CDclks are
> supported:
> -	 *   200MHz
> -	 *   267MHz
> -	 *   320/333MHz (depends on HPLL freq)
> -	 *   400MHz (VLV only)
> -	 * So we check to see whether we're above 90% (VLV) or 95% (CHV)
> -	 * of the lower bin and adjust if needed.
> -	 *
> -	 * We seem to get an unstable or solid color picture at 200MHz.
> -	 * Not sure what's wrong. For now use 200MHz only when all pipes
> -	 * are off.
> -	 */
> -	if (!IS_CHERRYVIEW(dev_priv) &&
> -	    max_pixclk > freq_320*limit/100)
> -		return 400000;
> -	else if (max_pixclk > 266667*limit/100)
> -		return freq_320;
> -	else if (max_pixclk > 0)
> -		return 266667;
> -	else
> -		return 200000;
> -}
> -
> -static int glk_calc_cdclk(int max_pixclk)
> -{
> -	if (max_pixclk > 2 * 158400)
> -		return 316800;
> -	else if (max_pixclk > 2 * 79200)
> -		return 158400;
> -	else
> -		return 79200;
> -}
> -
> -static int bxt_calc_cdclk(int max_pixclk)
> -{
> -	if (max_pixclk > 576000)
> -		return 624000;
> -	else if (max_pixclk > 384000)
> -		return 576000;
> -	else if (max_pixclk > 288000)
> -		return 384000;
> -	else if (max_pixclk > 144000)
> -		return 288000;
> -	else
> -		return 144000;
> -}
> -
> -static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> -	struct drm_device *dev = state->dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	int max_pixclk = intel_max_pixel_rate(state);
> -	struct intel_atomic_state *intel_state =
> -		to_intel_atomic_state(state);
> -
> -	intel_state->cdclk = intel_state->dev_cdclk =
> -		valleyview_calc_cdclk(dev_priv, max_pixclk);
> -
> -	if (!intel_state->active_crtcs)
> -		intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0);
> -
> -	return 0;
> -}
> -
> -static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(state->dev);
> -	int max_pixclk = intel_max_pixel_rate(state);
> -	struct intel_atomic_state *intel_state =
> -		to_intel_atomic_state(state);
> -	int cdclk;
> -
> -	if (IS_GEMINILAKE(dev_priv))
> -		cdclk = glk_calc_cdclk(max_pixclk);
> -	else
> -		cdclk = bxt_calc_cdclk(max_pixclk);
> -
> -	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> -
> -	if (!intel_state->active_crtcs) {
> -		if (IS_GEMINILAKE(dev_priv))
> -			cdclk = glk_calc_cdclk(0);
> -		else
> -			cdclk = bxt_calc_cdclk(0);
> -
> -		intel_state->dev_cdclk = cdclk;
> -	}
> -
> -	return 0;
> -}
> -
> -static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
> -{
> -	unsigned int credits, default_credits;
> -
> -	if (IS_CHERRYVIEW(dev_priv))
> -		default_credits = PFI_CREDIT(12);
> -	else
> -		default_credits = PFI_CREDIT(8);
> -
> -	if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
> -		/* CHV suggested value is 31 or 63 */
> -		if (IS_CHERRYVIEW(dev_priv))
> -			credits = PFI_CREDIT_63;
> -		else
> -			credits = PFI_CREDIT(15);
> -	} else {
> -		credits = default_credits;
> -	}
> -
> -	/*
> -	 * WA - write default credits before re-programming
> -	 * FIXME: should we also set the resend bit here?
> -	 */
> -	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> -		   default_credits);
> -
> -	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> -		   credits | PFI_CREDIT_RESEND);
> -
> -	/*
> -	 * FIXME is this guaranteed to clear
> -	 * immediately or should we poll for it?
> -	 */
> -	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
> -}
> -
> -static void valleyview_modeset_commit_cdclk(struct drm_atomic_state
> *old_state)
> -{
> -	struct drm_device *dev = old_state->dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct intel_atomic_state *old_intel_state =
> -		to_intel_atomic_state(old_state);
> -	unsigned req_cdclk = old_intel_state->dev_cdclk;
> -
> -	/*
> -	 * FIXME: We can end up here with all power domains off, yet
> -	 * with a CDCLK frequency other than the minimum. To account
> -	 * for this take the PIPE-A power domain, which covers the HW
> -	 * blocks needed for the following programming. This can be
> -	 * removed once it's guaranteed that we get here either with
> -	 * the minimum CDCLK set, or the required power domains
> -	 * enabled.
> -	 */
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> -
> -	if (IS_CHERRYVIEW(dev_priv))
> -		cherryview_set_cdclk(dev, req_cdclk);
> -	else
> -		valleyview_set_cdclk(dev, req_cdclk);
> -
> -	vlv_program_pfi_credits(dev_priv);
> -
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> -}
> -
> -static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> -				   struct drm_atomic_state *old_state)
> -{
> -	struct drm_crtc *crtc = pipe_config->base.crtc;
> -	struct drm_device *dev = crtc->dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	int pipe = intel_crtc->pipe;
> -
> -	if (WARN_ON(intel_crtc->active))
> -		return;
> -
> -	if (intel_crtc_has_dp_encoder(intel_crtc->config))
> -		intel_dp_set_m_n(intel_crtc, M1_N1);
> -
> -	intel_set_pipe_timings(intel_crtc);
> -	intel_set_pipe_src_size(intel_crtc);
> -
> -	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> -		struct drm_i915_private *dev_priv = to_i915(dev);
> -
> -		I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
> -		I915_WRITE(CHV_CANVAS(pipe), 0);
> -	}
> -
> -	i9xx_set_pipeconf(intel_crtc);
> -
> -	intel_crtc->active = true;
> -
> -	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
> -
> -	intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
> -
> -	if (IS_CHERRYVIEW(dev_priv)) {
> -		chv_prepare_pll(intel_crtc, intel_crtc->config);
> -		chv_enable_pll(intel_crtc, intel_crtc->config);
> -	} else {
> -		vlv_prepare_pll(intel_crtc, intel_crtc->config);
> -		vlv_enable_pll(intel_crtc, intel_crtc->config);
> -	}
> -
> -	intel_encoders_pre_enable(crtc, pipe_config, old_state);
> -
> -	i9xx_pfit_enable(intel_crtc);
> -
> -	intel_color_load_luts(&pipe_config->base);
> -
> -	intel_update_watermarks(intel_crtc);
> -	intel_enable_pipe(intel_crtc);
> -
> -	assert_vblank_disabled(crtc);
> -	drm_crtc_vblank_on(crtc);
> -
> -	intel_encoders_enable(crtc, pipe_config, old_state);
> -}
> -
> -static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
> -{
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -
> -	I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
> -	I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
> -}
> -
> -static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
> -			     struct drm_atomic_state *old_state)
> -{
> -	struct drm_crtc *crtc = pipe_config->base.crtc;
> -	struct drm_device *dev = crtc->dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	enum pipe pipe = intel_crtc->pipe;
> -
> -	if (WARN_ON(intel_crtc->active))
> -		return;
> -
> -	i9xx_set_pll_dividers(intel_crtc);
> -
> -	if (intel_crtc_has_dp_encoder(intel_crtc->config))
> -		intel_dp_set_m_n(intel_crtc, M1_N1);
> -
> -	intel_set_pipe_timings(intel_crtc);
> -	intel_set_pipe_src_size(intel_crtc);
> -
> -	i9xx_set_pipeconf(intel_crtc);
> -
> -	intel_crtc->active = true;
> -
> -	if (!IS_GEN2(dev_priv))
> -		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
> -
> -	intel_encoders_pre_enable(crtc, pipe_config, old_state);
> -
> -	i9xx_enable_pll(intel_crtc);
> -
> -	i9xx_pfit_enable(intel_crtc);
> -
> -	intel_color_load_luts(&pipe_config->base);
> -
> -	intel_update_watermarks(intel_crtc);
> -	intel_enable_pipe(intel_crtc);
> -
> -	assert_vblank_disabled(crtc);
> -	drm_crtc_vblank_on(crtc);
> -
> -	intel_encoders_enable(crtc, pipe_config, old_state);
> -}
> -
> -static void i9xx_pfit_disable(struct intel_crtc *crtc)
> -{
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -
> -	if (!crtc->config->gmch_pfit.control)
> -		return;
> -
> -	assert_pipe_disabled(dev_priv, crtc->pipe);
> -
> -	DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
> -			 I915_READ(PFIT_CONTROL));
> -	I915_WRITE(PFIT_CONTROL, 0);
> -}
> -
> -static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
> -			      struct drm_atomic_state *old_state)
> -{
> -	struct drm_crtc *crtc = old_crtc_state->base.crtc;
> -	struct drm_device *dev = crtc->dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	int pipe = intel_crtc->pipe;
> -
> -	/*
> -	 * On gen2 planes are double buffered but the pipe isn't, so we must
> -	 * wait for planes to fully turn off before disabling the pipe.
> -	 */
> -	if (IS_GEN2(dev_priv))
> -		intel_wait_for_vblank(dev_priv, pipe);
> -
> -	intel_encoders_disable(crtc, old_crtc_state, old_state);
> -
> -	drm_crtc_vblank_off(crtc);
> -	assert_vblank_disabled(crtc);
> -
> -	intel_disable_pipe(intel_crtc);
> -
> -	i9xx_pfit_disable(intel_crtc);
> -
> -	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
> -
> -	if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
> -		if (IS_CHERRYVIEW(dev_priv))
> -			chv_disable_pll(dev_priv, pipe);
> -		else if (IS_VALLEYVIEW(dev_priv))
> -			vlv_disable_pll(dev_priv, pipe);
> -		else
> -			i9xx_disable_pll(intel_crtc);
> -	}
> -
> -	intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
> -
> -	if (!IS_GEN2(dev_priv))
> -		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> -}
> -
> -static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
> -{
> -	struct intel_encoder *encoder;
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> -	enum intel_display_power_domain domain;
> -	unsigned long domains;
> -	struct drm_atomic_state *state;
> -	struct intel_crtc_state *crtc_state;
> -	int ret;
> -
> -	if (!intel_crtc->active)
> -		return;
> -
> -	if (to_intel_plane_state(crtc->primary->state)->base.visible) {
> -		WARN_ON(intel_crtc->flip_work);
> -
> -		intel_pre_disable_primary_noatomic(crtc);
> -
> -		intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc-
> >primary));
> -		to_intel_plane_state(crtc->primary->state)->base.visible =
> false;
> -	}
> -
> -	state = drm_atomic_state_alloc(crtc->dev);
> -	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
> -
> -	/* Everything's already locked, -EDEADLK can't happen. */
> -	crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
> -	ret = drm_atomic_add_affected_connectors(state, crtc);
> -
> -	WARN_ON(IS_ERR(crtc_state) || ret);
> -
> -	dev_priv->display.crtc_disable(crtc_state, state);
> -
> -	drm_atomic_state_put(state);
> -
> -	DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now
> disabled\n",
> -		      crtc->base.id, crtc->name);
> +	DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now
> disabled\n",
> +		      crtc->base.id, crtc->name);
>  
>  	WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0);
>  	crtc->state->active = false;
> @@ -7124,543 +6182,121 @@ static int ironlake_fdi_compute_config(struct
> intel_crtc *intel_crtc,
>  		goto retry;
>  	}
>  
> -	if (needs_recompute)
> -		return RETRY;
> -
> -	return ret;
> -}
> -
> -static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
> -				     struct intel_crtc_state *pipe_config)
> -{
> -	if (pipe_config->pipe_bpp > 24)
> -		return false;
> -
> -	/* HSW can handle pixel rate up to cdclk? */
> -	if (IS_HASWELL(dev_priv))
> -		return true;
> -
> -	/*
> -	 * We compare against max which means we must take
> -	 * the increased cdclk requirement into account when
> -	 * calculating the new cdclk.
> -	 *
> -	 * Should measure whether using a lower cdclk w/o IPS
> -	 */
> -	return pipe_config->pixel_rate <=
> -		dev_priv->max_cdclk_freq * 95 / 100;
> -}
> -
> -static void hsw_compute_ips_config(struct intel_crtc *crtc,
> -				   struct intel_crtc_state *pipe_config)
> -{
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -
> -	pipe_config->ips_enabled = i915.enable_ips &&
> -		hsw_crtc_supports_ips(crtc) &&
> -		pipe_config_supports_ips(dev_priv, pipe_config);
> -}
> -
> -static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
> -{
> -	const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -
> -	/* GDG double wide on either pipe, otherwise pipe A only */
> -	return INTEL_INFO(dev_priv)->gen < 4 &&
> -		(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
> -}
> -
> -static void intel_crtc_compute_pixel_rate(struct intel_crtc_state
> *crtc_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc-
> >dev);
> -
> -	if (HAS_GMCH_DISPLAY(dev_priv))
> -		/* FIXME calculate proper pipe pixel rate GMCH pfit */
> -		crtc_state->pixel_rate =
> -			crtc_state->base.adjusted_mode.crtc_clock;
> -	else
> -		crtc_state->pixel_rate =
> -			ilk_pipe_pixel_rate(crtc_state);
> -}
> -
> -static int intel_crtc_compute_config(struct intel_crtc *crtc,
> -				     struct intel_crtc_state *pipe_config)
> -{
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	const struct drm_display_mode *adjusted_mode = &pipe_config-
> >base.adjusted_mode;
> -	int clock_limit = dev_priv->max_dotclk_freq;
> -
> -	if (INTEL_GEN(dev_priv) < 4) {
> -		clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
> -
> -		/*
> -		 * Enable double wide mode when the dot clock
> -		 * is > 90% of the (display) core speed.
> -		 */
> -		if (intel_crtc_supports_double_wide(crtc) &&
> -		    adjusted_mode->crtc_clock > clock_limit) {
> -			clock_limit = dev_priv->max_dotclk_freq;
> -			pipe_config->double_wide = true;
> -		}
> -	}
> -
> -	if (adjusted_mode->crtc_clock > clock_limit) {
> -		DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max:
> %d kHz, double wide: %s)\n",
> -			      adjusted_mode->crtc_clock, clock_limit,
> -			      yesno(pipe_config->double_wide));
> -		return -EINVAL;
> -	}
> -
> -	/*
> -	 * Pipe horizontal size must be even in:
> -	 * - DVO ganged mode
> -	 * - LVDS dual channel mode
> -	 * - Double wide pipe
> -	 */
> -	if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
> -	     intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
> -		pipe_config->pipe_src_w &= ~1;
> -
> -	/* Cantiga+ cannot handle modes with a hsync front porch of 0.
> -	 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
> -	 */
> -	if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
> -		adjusted_mode->crtc_hsync_start == adjusted_mode-
> >crtc_hdisplay)
> -		return -EINVAL;
> -
> -	intel_crtc_compute_pixel_rate(pipe_config);
> -
> -	if (HAS_IPS(dev_priv))
> -		hsw_compute_ips_config(crtc, pipe_config);
> -
> -	if (pipe_config->has_pch_encoder)
> -		return ironlake_fdi_compute_config(crtc, pipe_config);
> -
> -	return 0;
> -}
> -
> -static int skylake_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	u32 cdctl;
> -
> -	skl_dpll0_update(dev_priv);
> -
> -	if (dev_priv->cdclk_pll.vco == 0)
> -		return dev_priv->cdclk_pll.ref;
> -
> -	cdctl = I915_READ(CDCLK_CTL);
> -
> -	if (dev_priv->cdclk_pll.vco == 8640000) {
> -		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> -		case CDCLK_FREQ_450_432:
> -			return 432000;
> -		case CDCLK_FREQ_337_308:
> -			return 308571;
> -		case CDCLK_FREQ_540:
> -			return 540000;
> -		case CDCLK_FREQ_675_617:
> -			return 617143;
> -		default:
> -			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> -		}
> -	} else {
> -		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> -		case CDCLK_FREQ_450_432:
> -			return 450000;
> -		case CDCLK_FREQ_337_308:
> -			return 337500;
> -		case CDCLK_FREQ_540:
> -			return 540000;
> -		case CDCLK_FREQ_675_617:
> -			return 675000;
> -		default:
> -			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> -		}
> -	}
> -
> -	return dev_priv->cdclk_pll.ref;
> -}
> -
> -static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> -{
> -	u32 val;
> -
> -	dev_priv->cdclk_pll.ref = 19200;
> -	dev_priv->cdclk_pll.vco = 0;
> -
> -	val = I915_READ(BXT_DE_PLL_ENABLE);
> -	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
> -		return;
> -
> -	if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
> -		return;
> -
> -	val = I915_READ(BXT_DE_PLL_CTL);
> -	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
> -		dev_priv->cdclk_pll.ref;
> -}
> -
> -static int broxton_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	u32 divider;
> -	int div, vco;
> -
> -	bxt_de_pll_update(dev_priv);
> -
> -	vco = dev_priv->cdclk_pll.vco;
> -	if (vco == 0)
> -		return dev_priv->cdclk_pll.ref;
> -
> -	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
> -
> -	switch (divider) {
> -	case BXT_CDCLK_CD2X_DIV_SEL_1:
> -		div = 2;
> -		break;
> -	case BXT_CDCLK_CD2X_DIV_SEL_1_5:
> -		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> -		div = 3;
> -		break;
> -	case BXT_CDCLK_CD2X_DIV_SEL_2:
> -		div = 4;
> -		break;
> -	case BXT_CDCLK_CD2X_DIV_SEL_4:
> -		div = 8;
> -		break;
> -	default:
> -		MISSING_CASE(divider);
> -		return dev_priv->cdclk_pll.ref;
> -	}
> -
> -	return DIV_ROUND_CLOSEST(vco, div);
> -}
> -
> -static int broadwell_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	uint32_t lcpll = I915_READ(LCPLL_CTL);
> -	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> -
> -	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> -		return 800000;
> -	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> -		return 450000;
> -	else if (freq == LCPLL_CLK_FREQ_450)
> -		return 450000;
> -	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
> -		return 540000;
> -	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
> -		return 337500;
> -	else
> -		return 675000;
> -}
> -
> -static int haswell_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	uint32_t lcpll = I915_READ(LCPLL_CTL);
> -	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> -
> -	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> -		return 800000;
> -	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> -		return 450000;
> -	else if (freq == LCPLL_CLK_FREQ_450)
> -		return 450000;
> -	else if (IS_HSW_ULT(dev_priv))
> -		return 337500;
> -	else
> -		return 540000;
> -}
> -
> -static int valleyview_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
> -				      CCK_DISPLAY_CLOCK_CONTROL);
> -}
> -
> -static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	return 450000;
> -}
> -
> -static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	return 400000;
> -}
> -
> -static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	return 333333;
> -}
> -
> -static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	return 200000;
> -}
> -
> -static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	u16 gcfgc = 0;
> -
> -	pci_read_config_word(pdev, GCFGC, &gcfgc);
> -
> -	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> -	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
> -		return 266667;
> -	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
> -		return 333333;
> -	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
> -		return 444444;
> -	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
> -		return 200000;
> -	default:
> -		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
> -	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
> -		return 133333;
> -	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
> -		return 166667;
> -	}
> -}
> -
> -static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	u16 gcfgc = 0;
> -
> -	pci_read_config_word(pdev, GCFGC, &gcfgc);
> -
> -	if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
> -		return 133333;
> -	else {
> -		switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> -		case GC_DISPLAY_CLOCK_333_MHZ:
> -			return 333333;
> -		default:
> -		case GC_DISPLAY_CLOCK_190_200_MHZ:
> -			return 190000;
> -		}
> -	}
> -}
> -
> -static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	return 266667;
> +	if (needs_recompute)
> +		return RETRY;
> +
> +	return ret;
>  }
>  
> -static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> +static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
> +				     struct intel_crtc_state *pipe_config)
>  {
> -	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	u16 hpllcc = 0;
> -
> -	/*
> -	 * 852GM/852GMV only supports 133 MHz and the HPLLCC
> -	 * encoding is different :(
> -	 * FIXME is this the right way to detect 852GM/852GMV?
> -	 */
> -	if (pdev->revision == 0x1)
> -		return 133333;
> +	if (pipe_config->pipe_bpp > 24)
> +		return false;
>  
> -	pci_bus_read_config_word(pdev->bus,
> -				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
> +	/* HSW can handle pixel rate up to cdclk? */
> +	if (IS_HASWELL(dev_priv))
> +		return true;
>  
> -	/* Assume that the hardware is in the high speed state.  This
> -	 * should be the default.
> +	/*
> +	 * We compare against max which means we must take
> +	 * the increased cdclk requirement into account when
> +	 * calculating the new cdclk.
> +	 *
> +	 * Should measure whether using a lower cdclk w/o IPS
>  	 */
> -	switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
> -	case GC_CLOCK_133_200:
> -	case GC_CLOCK_133_200_2:
> -	case GC_CLOCK_100_200:
> -		return 200000;
> -	case GC_CLOCK_166_250:
> -		return 250000;
> -	case GC_CLOCK_100_133:
> -		return 133333;
> -	case GC_CLOCK_133_266:
> -	case GC_CLOCK_133_266_2:
> -	case GC_CLOCK_166_266:
> -		return 266667;
> -	}
> -
> -	/* Shouldn't happen */
> -	return 0;
> +	return pipe_config->pixel_rate <=
> +		dev_priv->max_cdclk_freq * 95 / 100;
>  }
>  
> -static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void hsw_compute_ips_config(struct intel_crtc *crtc,
> +				   struct intel_crtc_state *pipe_config)
>  {
> -	return 133333;
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +
> +	pipe_config->ips_enabled = i915.enable_ips &&
> +		hsw_crtc_supports_ips(crtc) &&
> +		pipe_config_supports_ips(dev_priv, pipe_config);
>  }
>  
> -static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
> +static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
>  {
> -	static const unsigned int blb_vco[8] = {
> -		[0] = 3200000,
> -		[1] = 4000000,
> -		[2] = 5333333,
> -		[3] = 4800000,
> -		[4] = 6400000,
> -	};
> -	static const unsigned int pnv_vco[8] = {
> -		[0] = 3200000,
> -		[1] = 4000000,
> -		[2] = 5333333,
> -		[3] = 4800000,
> -		[4] = 2666667,
> -	};
> -	static const unsigned int cl_vco[8] = {
> -		[0] = 3200000,
> -		[1] = 4000000,
> -		[2] = 5333333,
> -		[3] = 6400000,
> -		[4] = 3333333,
> -		[5] = 3566667,
> -		[6] = 4266667,
> -	};
> -	static const unsigned int elk_vco[8] = {
> -		[0] = 3200000,
> -		[1] = 4000000,
> -		[2] = 5333333,
> -		[3] = 4800000,
> -	};
> -	static const unsigned int ctg_vco[8] = {
> -		[0] = 3200000,
> -		[1] = 4000000,
> -		[2] = 5333333,
> -		[3] = 6400000,
> -		[4] = 2666667,
> -		[5] = 4266667,
> -	};
> -	const unsigned int *vco_table;
> -	unsigned int vco;
> -	uint8_t tmp = 0;
> -
> -	/* FIXME other chipsets? */
> -	if (IS_GM45(dev_priv))
> -		vco_table = ctg_vco;
> -	else if (IS_G4X(dev_priv))
> -		vco_table = elk_vco;
> -	else if (IS_I965GM(dev_priv))
> -		vco_table = cl_vco;
> -	else if (IS_PINEVIEW(dev_priv))
> -		vco_table = pnv_vco;
> -	else if (IS_G33(dev_priv))
> -		vco_table = blb_vco;
> -	else
> -		return 0;
> -
> -	tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
> -
> -	vco = vco_table[tmp & 0x7];
> -	if (vco == 0)
> -		DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
> -	else
> -		DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
> +	const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  
> -	return vco;
> +	/* GDG double wide on either pipe, otherwise pipe A only */
> +	return INTEL_INFO(dev_priv)->gen < 4 &&
> +		(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
>  }
>  
> -static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
> +static void intel_crtc_compute_pixel_rate(struct intel_crtc_state
> *crtc_state)
>  {
> -	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> -	uint16_t tmp = 0;
> -
> -	pci_read_config_word(pdev, GCFGC, &tmp);
> -
> -	cdclk_sel = (tmp >> 12) & 0x1;
> +	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc-
> >dev);
>  
> -	switch (vco) {
> -	case 2666667:
> -	case 4000000:
> -	case 5333333:
> -		return cdclk_sel ? 333333 : 222222;
> -	case 3200000:
> -		return cdclk_sel ? 320000 : 228571;
> -	default:
> -		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u,
> CFGC=0x%04x\n", vco, tmp);
> -		return 222222;
> -	}
> +	if (HAS_GMCH_DISPLAY(dev_priv))
> +		/* FIXME calculate proper pipe pixel rate GMCH pfit */
> +		crtc_state->pixel_rate =
> +			crtc_state->base.adjusted_mode.crtc_clock;
> +	else
> +		crtc_state->pixel_rate =
> +			ilk_pipe_pixel_rate(crtc_state);
>  }
>  
> -static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> +static int intel_crtc_compute_config(struct intel_crtc *crtc,
> +				     struct intel_crtc_state *pipe_config)
>  {
> -	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	static const uint8_t div_3200[] = { 16, 10,  8 };
> -	static const uint8_t div_4000[] = { 20, 12, 10 };
> -	static const uint8_t div_5333[] = { 24, 16, 14 };
> -	const uint8_t *div_table;
> -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> -	uint16_t tmp = 0;
> -
> -	pci_read_config_word(pdev, GCFGC, &tmp);
> -
> -	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	const struct drm_display_mode *adjusted_mode = &pipe_config-
> >base.adjusted_mode;
> +	int clock_limit = dev_priv->max_dotclk_freq;
>  
> -	if (cdclk_sel >= ARRAY_SIZE(div_3200))
> -		goto fail;
> +	if (INTEL_GEN(dev_priv) < 4) {
> +		clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
>  
> -	switch (vco) {
> -	case 3200000:
> -		div_table = div_3200;
> -		break;
> -	case 4000000:
> -		div_table = div_4000;
> -		break;
> -	case 5333333:
> -		div_table = div_5333;
> -		break;
> -	default:
> -		goto fail;
> +		/*
> +		 * Enable double wide mode when the dot clock
> +		 * is > 90% of the (display) core speed.
> +		 */
> +		if (intel_crtc_supports_double_wide(crtc) &&
> +		    adjusted_mode->crtc_clock > clock_limit) {
> +			clock_limit = dev_priv->max_dotclk_freq;
> +			pipe_config->double_wide = true;
> +		}
>  	}
>  
> -	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> -
> -fail:
> -	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%04x\n", vco, tmp);
> -	return 200000;
> -}
> -
> -static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> -	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
> -	static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
> -	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
> -	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
> -	const uint8_t *div_table;
> -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> -	uint16_t tmp = 0;
> +	if (adjusted_mode->crtc_clock > clock_limit) {
> +		DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max:
> %d kHz, double wide: %s)\n",
> +			      adjusted_mode->crtc_clock, clock_limit,
> +			      yesno(pipe_config->double_wide));
> +		return -EINVAL;
> +	}
>  
> -	pci_read_config_word(pdev, GCFGC, &tmp);
> +	/*
> +	 * Pipe horizontal size must be even in:
> +	 * - DVO ganged mode
> +	 * - LVDS dual channel mode
> +	 * - Double wide pipe
> +	 */
> +	if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
> +	     intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
> +		pipe_config->pipe_src_w &= ~1;
>  
> -	cdclk_sel = (tmp >> 4) & 0x7;
> +	/* Cantiga+ cannot handle modes with a hsync front porch of 0.
> +	 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
> +	 */
> +	if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
> +		adjusted_mode->crtc_hsync_start == adjusted_mode-
> >crtc_hdisplay)
> +		return -EINVAL;
>  
> -	if (cdclk_sel >= ARRAY_SIZE(div_3200))
> -		goto fail;
> +	intel_crtc_compute_pixel_rate(pipe_config);
>  
> -	switch (vco) {
> -	case 3200000:
> -		div_table = div_3200;
> -		break;
> -	case 4000000:
> -		div_table = div_4000;
> -		break;
> -	case 4800000:
> -		div_table = div_4800;
> -		break;
> -	case 5333333:
> -		div_table = div_5333;
> -		break;
> -	default:
> -		goto fail;
> -	}
> +	if (HAS_IPS(dev_priv))
> +		hsw_compute_ips_config(crtc, pipe_config);
>  
> -	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> +	if (pipe_config->has_pch_encoder)
> +		return ironlake_fdi_compute_config(crtc, pipe_config);
>  
> -fail:
> -	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%08x\n", vco, tmp);
> -	return 190476;
> +	return 0;
>  }
>  
>  static void
> @@ -10225,245 +8861,6 @@ void hsw_disable_pc8(struct drm_i915_private
> *dev_priv)
>  	}
>  }
>  
> -static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> -	struct drm_device *dev = old_state->dev;
> -	struct intel_atomic_state *old_intel_state =
> -		to_intel_atomic_state(old_state);
> -	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> -
> -	bxt_set_cdclk(to_i915(dev), req_cdclk);
> -}
> -
> -static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state
> *crtc_state,
> -					  int pixel_rate)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc-
> >dev);
> -
> -	/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
> -	if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
> -		pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
> -
> -	/* BSpec says "Do not use DisplayPort with CDCLK less than
> -	 * 432 MHz, audio enabled, port width x4, and link rate
> -	 * HBR2 (5.4 GHz), or else there may be audio corruption or
> -	 * screen corruption."
> -	 */
> -	if (intel_crtc_has_dp_encoder(crtc_state) &&
> -	    crtc_state->has_audio &&
> -	    crtc_state->port_clock >= 540000 &&
> -	    crtc_state->lane_count == 4)
> -		pixel_rate = max(432000, pixel_rate);
> -
> -	return pixel_rate;
> -}
> -
> -/* compute the max rate for new configuration */
> -static int intel_max_pixel_rate(struct drm_atomic_state *state)
> -{
> -	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> -	struct drm_i915_private *dev_priv = to_i915(state->dev);
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *cstate;
> -	struct intel_crtc_state *crtc_state;
> -	unsigned max_pixel_rate = 0, i;
> -	enum pipe pipe;
> -
> -	memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
> -	       sizeof(intel_state->min_pixclk));
> -
> -	for_each_crtc_in_state(state, crtc, cstate, i) {
> -		int pixel_rate;
> -
> -		crtc_state = to_intel_crtc_state(cstate);
> -		if (!crtc_state->base.enable) {
> -			intel_state->min_pixclk[i] = 0;
> -			continue;
> -		}
> -
> -		pixel_rate = crtc_state->pixel_rate;
> -
> -		if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
> -			pixel_rate =
> bdw_adjust_min_pipe_pixel_rate(crtc_state,
> -								    pixel_rat
> e);
> -
> -		intel_state->min_pixclk[i] = pixel_rate;
> -	}
> -
> -	for_each_pipe(dev_priv, pipe)
> -		max_pixel_rate = max(intel_state->min_pixclk[pipe],
> max_pixel_rate);
> -
> -	return max_pixel_rate;
> -}
> -
> -static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	uint32_t val, data;
> -	int ret;
> -
> -	if (WARN((I915_READ(LCPLL_CTL) &
> -		  (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
> -		   LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
> -		   LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
> -		   LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
> -		 "trying to change cdclk frequency with cdclk not
> enabled\n"))
> -		return;
> -
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	ret = sandybridge_pcode_write(dev_priv,
> -				      BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ,
> 0x0);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> -	if (ret) {
> -		DRM_ERROR("failed to inform pcode about cdclk change\n");
> -		return;
> -	}
> -
> -	val = I915_READ(LCPLL_CTL);
> -	val |= LCPLL_CD_SOURCE_FCLK;
> -	I915_WRITE(LCPLL_CTL, val);
> -
> -	if (wait_for_us(I915_READ(LCPLL_CTL) &
> -			LCPLL_CD_SOURCE_FCLK_DONE, 1))
> -		DRM_ERROR("Switching to FCLK failed\n");
> -
> -	val = I915_READ(LCPLL_CTL);
> -	val &= ~LCPLL_CLK_FREQ_MASK;
> -
> -	switch (cdclk) {
> -	case 450000:
> -		val |= LCPLL_CLK_FREQ_450;
> -		data = 0;
> -		break;
> -	case 540000:
> -		val |= LCPLL_CLK_FREQ_54O_BDW;
> -		data = 1;
> -		break;
> -	case 337500:
> -		val |= LCPLL_CLK_FREQ_337_5_BDW;
> -		data = 2;
> -		break;
> -	case 675000:
> -		val |= LCPLL_CLK_FREQ_675_BDW;
> -		data = 3;
> -		break;
> -	default:
> -		WARN(1, "invalid cdclk frequency\n");
> -		return;
> -	}
> -
> -	I915_WRITE(LCPLL_CTL, val);
> -
> -	val = I915_READ(LCPLL_CTL);
> -	val &= ~LCPLL_CD_SOURCE_FCLK;
> -	I915_WRITE(LCPLL_CTL, val);
> -
> -	if (wait_for_us((I915_READ(LCPLL_CTL) &
> -			LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
> -		DRM_ERROR("Switching back to LCPLL failed\n");
> -
> -	mutex_lock(&dev_priv->rps.hw_lock);
> -	sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
> -
> -	I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
> -
> -	intel_update_cdclk(dev_priv);
> -
> -	WARN(cdclk != dev_priv->cdclk_freq,
> -	     "cdclk requested %d kHz but got %d kHz\n",
> -	     cdclk, dev_priv->cdclk_freq);
> -}
> -
> -static int broadwell_calc_cdclk(int max_pixclk)
> -{
> -	if (max_pixclk > 540000)
> -		return 675000;
> -	else if (max_pixclk > 450000)
> -		return 540000;
> -	else if (max_pixclk > 337500)
> -		return 450000;
> -	else
> -		return 337500;
> -}
> -
> -static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(state->dev);
> -	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> -	int max_pixclk = intel_max_pixel_rate(state);
> -	int cdclk;
> -
> -	/*
> -	 * FIXME should also account for plane ratio
> -	 * once 64bpp pixel formats are supported.
> -	 */
> -	cdclk = broadwell_calc_cdclk(max_pixclk);
> -
> -	if (cdclk > dev_priv->max_cdclk_freq) {
> -		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d
> kHz)\n",
> -			      cdclk, dev_priv->max_cdclk_freq);
> -		return -EINVAL;
> -	}
> -
> -	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> -	if (!intel_state->active_crtcs)
> -		intel_state->dev_cdclk = broadwell_calc_cdclk(0);
> -
> -	return 0;
> -}
> -
> -static void broadwell_modeset_commit_cdclk(struct drm_atomic_state
> *old_state)
> -{
> -	struct drm_device *dev = old_state->dev;
> -	struct intel_atomic_state *old_intel_state =
> -		to_intel_atomic_state(old_state);
> -	unsigned req_cdclk = old_intel_state->dev_cdclk;
> -
> -	broadwell_set_cdclk(dev, req_cdclk);
> -}
> -
> -static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> -	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> -	struct drm_i915_private *dev_priv = to_i915(state->dev);
> -	const int max_pixclk = intel_max_pixel_rate(state);
> -	int vco = intel_state->cdclk_pll_vco;
> -	int cdclk;
> -
> -	/*
> -	 * FIXME should also account for plane ratio
> -	 * once 64bpp pixel formats are supported.
> -	 */
> -	cdclk = skl_calc_cdclk(max_pixclk, vco);
> -
> -	/*
> -	 * FIXME move the cdclk caclulation to
> -	 * compute_config() so we can fail gracegully.
> -	 */
> -	if (cdclk > dev_priv->max_cdclk_freq) {
> -		DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
> -			  cdclk, dev_priv->max_cdclk_freq);
> -		cdclk = dev_priv->max_cdclk_freq;
> -	}
> -
> -	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> -	if (!intel_state->active_crtcs)
> -		intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
> -
> -	return 0;
> -}
> -
> -static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(old_state);
> -	unsigned int req_cdclk = intel_state->dev_cdclk;
> -	unsigned int req_vco = intel_state->cdclk_pll_vco;
> -
> -	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
> -}
> -
>  static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
>  				      struct intel_crtc_state *crtc_state)
>  {
> @@ -16019,6 +14416,8 @@ static const struct drm_mode_config_funcs
> intel_mode_funcs = {
>   */
>  void intel_init_display_hooks(struct drm_i915_private *dev_priv)
>  {
> +	intel_init_cdclk_hooks(dev_priv);
> +
>  	if (INTEL_INFO(dev_priv)->gen >= 9) {
>  		dev_priv->display.get_pipe_config = haswell_get_pipe_config;
>  		dev_priv->display.get_initial_plane_config =
> @@ -16087,52 +14486,6 @@ void intel_init_display_hooks(struct drm_i915_private
> *dev_priv)
>  		dev_priv->display.crtc_disable = i9xx_crtc_disable;
>  	}
>  
> -	/* Returns the core display clock speed */
> -	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> -		dev_priv->display.get_cdclk = skylake_get_cdclk;
> -	else if (IS_GEN9_LP(dev_priv))
> -		dev_priv->display.get_cdclk = broxton_get_cdclk;
> -	else if (IS_BROADWELL(dev_priv))
> -		dev_priv->display.get_cdclk = broadwell_get_cdclk;
> -	else if (IS_HASWELL(dev_priv))
> -		dev_priv->display.get_cdclk = haswell_get_cdclk;
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		dev_priv->display.get_cdclk = valleyview_get_cdclk;
> -	else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> -	else if (IS_GEN5(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
> -	else if (IS_GM45(dev_priv))
> -		dev_priv->display.get_cdclk = gm45_get_cdclk;
> -	else if (IS_G4X(dev_priv))
> -		dev_priv->display.get_cdclk = g33_get_cdclk;
> -	else if (IS_I965GM(dev_priv))
> -		dev_priv->display.get_cdclk = i965gm_get_cdclk;
> -	else if (IS_I965G(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> -	else if (IS_PINEVIEW(dev_priv))
> -		dev_priv->display.get_cdclk = pnv_get_cdclk;
> -	else if (IS_G33(dev_priv))
> -		dev_priv->display.get_cdclk = g33_get_cdclk;
> -	else if (IS_I945GM(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> -	else if (IS_I945G(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> -	else if (IS_I915GM(dev_priv))
> -		dev_priv->display.get_cdclk = i915gm_get_cdclk;
> -	else if (IS_I915G(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
> -	else if (IS_I865G(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
> -	else if (IS_I85X(dev_priv))
> -		dev_priv->display.get_cdclk = i85x_get_cdclk;
> -	else  if (IS_I845G(dev_priv))
> -		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> -	else { /* 830 */
> -		WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz
> CDCLK\n");
> -		dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
> -	}
> -
>  	if (IS_GEN5(dev_priv)) {
>  		dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
>  	} else if (IS_GEN6(dev_priv)) {
> @@ -16144,28 +14497,6 @@ void intel_init_display_hooks(struct drm_i915_private
> *dev_priv)
>  		dev_priv->display.fdi_link_train = hsw_fdi_link_train;
>  	}
>  
> -	if (IS_BROADWELL(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			broadwell_modeset_commit_cdclk;
> -		dev_priv->display.modeset_calc_cdclk =
> -			broadwell_modeset_calc_cdclk;
> -	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			valleyview_modeset_commit_cdclk;
> -		dev_priv->display.modeset_calc_cdclk =
> -			valleyview_modeset_calc_cdclk;
> -	} else if (IS_GEN9_LP(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			bxt_modeset_commit_cdclk;
> -		dev_priv->display.modeset_calc_cdclk =
> -			bxt_modeset_calc_cdclk;
> -	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			skl_modeset_commit_cdclk;
> -		dev_priv->display.modeset_calc_cdclk =
> -			skl_modeset_calc_cdclk;
> -	}
> -
>  	if (dev_priv->info.gen >= 9)
>  		dev_priv->display.update_crtcs = skl_update_crtcs;
>  	else
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index 3969e786d566..8d93b7bda3ff 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1220,12 +1220,19 @@ void intel_audio_codec_disable(struct intel_encoder
> *encoder);
>  void i915_audio_component_init(struct drm_i915_private *dev_priv);
>  void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
>  
> +/* intel_cdclk.c */
> +void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
> +void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
> +void intel_update_cdclk(struct drm_i915_private *dev_priv);
> +void intel_update_rawclk(struct drm_i915_private *dev_priv);
> +
>  /* intel_display.c */
>  enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
> -void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco);
>  void intel_update_rawclk(struct drm_i915_private *dev_priv);
>  int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
>  		      const char *name, u32 reg, int ref_freq);
> +int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> +			   const char *name, u32 reg);
>  void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv);
>  void lpt_disable_iclkip(struct drm_i915_private *dev_priv);
>  extern const struct drm_plane_funcs intel_plane_funcs;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c
  2016-12-22 13:10   ` Ander Conselvan De Oliveira
@ 2016-12-22 13:16     ` Joonas Lahtinen
  0 siblings, 0 replies; 40+ messages in thread
From: Joonas Lahtinen @ 2016-12-22 13:16 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira, ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On to, 2016-12-22 at 15:10 +0200, Ander Conselvan De Oliveira wrote:
> > On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > 
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Let's try to shrink intel_display.c a bit by moving the cdclk/rawclk
> > stuff to a new file. It's all reasonably self contained so we don't
> > even have to add that many non-static symbols.
> > 
> > We'll also take the opportunity to shuffle around the functions a bit
> > to get things in a more consistent order based on the platform.
> 
> Hmm, maybe this is the moment to add some kerneldoc to this stuff, or Daniel
> might be grumpy? :)
> 
> The new file makes sense, didn't really check the move line by line, but
> 

Would it be possible to create intel_cdclk.h header too? Untangling
these headers bit by bit is much more fun than in panic once when it's
really needed.

Regards, Joonas
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 06/14] drm/i915: Pass computed vco to bxt_set_cdclk()
  2016-12-19 17:28 ` [PATCH 06/14] drm/i915: Pass computed vco to bxt_set_cdclk() ville.syrjala
@ 2016-12-22 13:22   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-22 13:22 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Rather than compute the vco inside bxt_set_cdclk() let's precompute it
> outside and pass it in. A small step towards a fully precomputed cdclk
> state.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> ---
>  drivers/gpu/drm/i915/intel_cdclk.c | 33 +++++++++++++++++++--------------
>  1 file changed, 19 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> b/drivers/gpu/drm/i915/intel_cdclk.c
> index 1804c43553b7..89be610d0879 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -1080,15 +1080,11 @@ static void bxt_de_pll_enable(struct drm_i915_private
> *dev_priv, int vco)
>  	dev_priv->cdclk_pll.vco = vco;
>  }
>  
> -static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> +static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> +			  int cdclk, int vco)
>  {
>  	u32 val, divider;
> -	int vco, ret;
> -
> -	if (IS_GEMINILAKE(dev_priv))
> -		vco = glk_de_pll_vco(dev_priv, cdclk);
> -	else
> -		vco = bxt_de_pll_vco(dev_priv, cdclk);
> +	int ret;
>  
>  	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
>  			 cdclk, vco);
> @@ -1212,7 +1208,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private
> *dev_priv)
>  
>  void bxt_init_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	int cdclk;
> +	int cdclk, vco;
>  
>  	bxt_sanitize_cdclk(dev_priv);
>  
> @@ -1224,17 +1220,20 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
>  	 * - The initial CDCLK needs to be read from VBT.
>  	 *   Need to make this change after VBT has changes for BXT.
>  	 */
> -	if (IS_GEMINILAKE(dev_priv))
> +	if (IS_GEMINILAKE(dev_priv)) {
>  		cdclk = glk_calc_cdclk(0);
> -	else
> +		vco = glk_de_pll_vco(dev_priv, cdclk);
> +	} else {
>  		cdclk = bxt_calc_cdclk(0);
> +		vco = bxt_de_pll_vco(dev_priv, cdclk);
> +	}
>  
> -	bxt_set_cdclk(dev_priv, cdclk);
> +	bxt_set_cdclk(dev_priv, cdclk, vco);
>  }
>  
>  void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
> +	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
>  }
>  
>  static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state
> *crtc_state,
> @@ -1454,12 +1453,18 @@ static int bxt_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  
>  static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
> -	struct drm_device *dev = old_state->dev;
> +	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
>  	struct intel_atomic_state *old_intel_state =
>  		to_intel_atomic_state(old_state);
>  	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +	unsigned int req_vco;
> +
> +	if (IS_GEMINILAKE(dev_priv))
> +		req_vco = glk_de_pll_vco(dev_priv, req_cdclk);
> +	else
> +		req_vco = bxt_de_pll_vco(dev_priv, req_cdclk);
>  
> -	bxt_set_cdclk(to_i915(dev), req_cdclk);
> +	bxt_set_cdclk(dev_priv, req_cdclk, req_vco);
>  }
>  
>  static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure
  2016-12-19 17:28 ` [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure ville.syrjala
@ 2016-12-22 14:14   ` Ander Conselvan De Oliveira
  2016-12-22 14:33     ` Ville Syrjälä
  0 siblings, 1 reply; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-22 14:14 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Introduce intel_cdclk state which for now will track the cdclk
> frequency, the vco frequency and the reference frequency (not sure we
> want the last one, but I put it there anyway). We'll also make the
> .get_cdclk() function fill out this state structure rather than
> just returning the current cdclk frequency.
> 
> One immediate benefit is that calling .get_cdclk() will no longer
> clobber state stored under dev_priv unless ex[plicitly told to do

Typo: ex[plicity

> so. Previously it clobbered the vco and reference clocks stored
> there on some platforms.
> 
> We'll expand the use of this structure to actually precomputing the
> state and whatnot later.
> 
> v2: Constify intel_cdclk_state_compare()
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

A couple more comments beloew, but either way,

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> ---
>  drivers/gpu/drm/i915/i915_debugfs.c     |   2 +-
>  drivers/gpu/drm/i915/i915_drv.h         |  14 +-
>  drivers/gpu/drm/i915/intel_audio.c      |   2 +-
>  drivers/gpu/drm/i915/intel_cdclk.c      | 359 ++++++++++++++++++--------------
>  drivers/gpu/drm/i915/intel_display.c    |  18 +-
>  drivers/gpu/drm/i915/intel_dp.c         |   2 +-
>  drivers/gpu/drm/i915/intel_drv.h        |   3 +
>  drivers/gpu/drm/i915/intel_fbc.c        |   2 +-
>  drivers/gpu/drm/i915/intel_panel.c      |   4 +-
>  drivers/gpu/drm/i915/intel_runtime_pm.c |   5 +-
>  10 files changed, 240 insertions(+), 171 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 15deb2bc568b..c0171eef8f96 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1235,7 +1235,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
>  		seq_puts(m, "no P-state info available\n");
>  	}
>  
> -	seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk_freq);
> +	seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk.hw.cdclk);
>  	seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
>  	seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 393b34fb2d1a..a4f1231ff8ca 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -609,9 +609,11 @@ struct intel_initial_plane_config;
>  struct intel_crtc;
>  struct intel_limit;
>  struct dpll;
> +struct intel_cdclk_state;
>  
>  struct drm_i915_display_funcs {
> -	int (*get_cdclk)(struct drm_i915_private *dev_priv);
> +	void (*get_cdclk)(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state);
>  	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
>  	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
>  	int (*compute_intermediate_wm)(struct drm_device *dev,
> @@ -2126,6 +2128,10 @@ struct i915_oa_ops {
>  	bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv);
>  };
>  
> +struct intel_cdclk_state {
> +	unsigned int cdclk, vco, ref;
> +};
> +

Maybe document the fields while at it.

>  struct drm_i915_private {
>  	struct drm_device drm;
>  
> @@ -2229,7 +2235,7 @@ struct drm_i915_private {
>  
>  	unsigned int fsb_freq, mem_freq, is_ddr3;
>  	unsigned int skl_preferred_vco_freq;
> -	unsigned int cdclk_freq, max_cdclk_freq;
> +	unsigned int max_cdclk_freq;
>  
>  	/*
>  	 * For reading holding any crtc lock is sufficient,
> @@ -2243,8 +2249,8 @@ struct drm_i915_private {
>  	unsigned int czclk_freq;
>  
>  	struct {
> -		unsigned int vco, ref;
> -	} cdclk_pll;
> +		struct intel_cdclk_state hw;
> +	} cdclk;
>  
>  	/**
>  	 * wq - Driver workqueue for GEM.
> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> index 3bbc96c1767f..a292246995ef 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -734,7 +734,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
>  	if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
>  		return -ENODEV;
>  
> -	return dev_priv->cdclk_freq;
> +	return dev_priv->cdclk.hw.cdclk;
>  }
>  
>  /*
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
> index 89be610d0879..13c3b5555473 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -23,37 +23,44 @@
>  
>  #include "intel_drv.h"
>  
> -static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv,
> +				   struct intel_cdclk_state *cdclk_state)
>  {
> -	return 133333;
> +	cdclk_state->cdclk = 133333;
>  }
>  
> -static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv,
> +				   struct intel_cdclk_state *cdclk_state)
>  {
> -	return 200000;
> +	cdclk_state->cdclk = 200000;
>  }
>  
> -static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv,
> +				   struct intel_cdclk_state *cdclk_state)
>  {
> -	return 266667;
> +	cdclk_state->cdclk = 266667;
>  }
>  
> -static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv,
> +				   struct intel_cdclk_state *cdclk_state)
>  {
> -	return 333333;
> +	cdclk_state->cdclk = 333333;
>  }
>  
> -static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv,
> +				   struct intel_cdclk_state *cdclk_state)
>  {
> -	return 400000;
> +	cdclk_state->cdclk = 400000;
>  }
>  
> -static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
> +				   struct intel_cdclk_state *cdclk_state)
>  {
> -	return 450000;
> +	cdclk_state->cdclk = 450000;
>  }
>  
> -static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> +static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
> +			   struct intel_cdclk_state *cdclk_state)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u16 hpllcc = 0;
> @@ -63,8 +70,10 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
>  	 * encoding is different :(
>  	 * FIXME is this the right way to detect 852GM/852GMV?
>  	 */
> -	if (pdev->revision == 0x1)
> -		return 133333;
> +	if (pdev->revision == 0x1) {
> +		cdclk_state->cdclk = 133333;
> +		return;
> +	}
>  
>  	pci_bus_read_config_word(pdev->bus,
>  				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
> @@ -76,37 +85,43 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
>  	case GC_CLOCK_133_200:
>  	case GC_CLOCK_133_200_2:
>  	case GC_CLOCK_100_200:
> -		return 200000;
> +		cdclk_state->cdclk = 200000;
> +		break;
>  	case GC_CLOCK_166_250:
> -		return 250000;
> +		cdclk_state->cdclk = 250000;
> +		break;
>  	case GC_CLOCK_100_133:
> -		return 133333;
> +		cdclk_state->cdclk = 133333;
> +		break;
>  	case GC_CLOCK_133_266:
>  	case GC_CLOCK_133_266_2:
>  	case GC_CLOCK_166_266:
> -		return 266667;
> +		cdclk_state->cdclk = 266667;
> +		break;
>  	}
> -
> -	/* Shouldn't happen */
> -	return 0;
>  }
>  
> -static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
> +static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
> +			     struct intel_cdclk_state *cdclk_state)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u16 gcfgc = 0;
>  
>  	pci_read_config_word(pdev, GCFGC, &gcfgc);
>  
> -	if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
> -		return 133333;
> +	if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
> +		cdclk_state->cdclk = 133333;
> +		return;
> +	}
>  
>  	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
>  	case GC_DISPLAY_CLOCK_333_MHZ:
> -		return 333333;
> +		cdclk_state->cdclk = 333333;
> +		break;
>  	default:
>  	case GC_DISPLAY_CLOCK_190_200_MHZ:
> -		return 190000;
> +		cdclk_state->cdclk = 190000;
> +		break;
>  	}
>  }
>  
> @@ -178,7 +193,8 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
>  	return vco;
>  }
>  
> -static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> +static void g33_get_cdclk(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
> @@ -186,9 +202,11 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
>  	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
>  	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
>  	const uint8_t *div_table;
> -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> +	unsigned int cdclk_sel;
>  	uint16_t tmp = 0;
>  
> +	cdclk_state->vco = intel_hpll_vco(dev_priv);
> +
>  	pci_read_config_word(pdev, GCFGC, &tmp);
>  
>  	cdclk_sel = (tmp >> 4) & 0x7;
> @@ -196,7 +214,7 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
>  	if (cdclk_sel >= ARRAY_SIZE(div_3200))
>  		goto fail;
>  
> -	switch (vco) {
> +	switch (cdclk_state->vco) {
>  	case 3200000:
>  		div_table = div_3200;
>  		break;
> @@ -213,15 +231,18 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
>  		goto fail;
>  	}
>  
> -	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> +	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
> +					       div_table[cdclk_sel]);
> +	return;
>  
>  fail:
>  	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
> -		  vco, tmp);
> -	return 190476;
> +		  cdclk_state->vco, tmp);
> +	cdclk_state->cdclk = 190476;
>  }
>  
> -static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
> +static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u16 gcfgc = 0;
> @@ -230,32 +251,41 @@ static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
>  
>  	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
>  	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
> -		return 266667;
> +		cdclk_state->cdclk = 266667;
> +		break;
>  	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
> -		return 333333;
> +		cdclk_state->cdclk = 333333;
> +		break;
>  	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
> -		return 444444;
> +		cdclk_state->cdclk = 444444;
> +		break;
>  	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
> -		return 200000;
> +		cdclk_state->cdclk = 200000;
> +		break;
>  	default:
>  		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
>  	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
> -		return 133333;
> +		cdclk_state->cdclk = 133333;
> +		break;
>  	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
> -		return 166667;
> +		cdclk_state->cdclk = 166667;
> +		break;
>  	}
>  }
>  
> -static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> +static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
> +			     struct intel_cdclk_state *cdclk_state)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	static const uint8_t div_3200[] = { 16, 10,  8 };
>  	static const uint8_t div_4000[] = { 20, 12, 10 };
>  	static const uint8_t div_5333[] = { 24, 16, 14 };
>  	const uint8_t *div_table;
> -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> +	unsigned int cdclk_sel;
>  	uint16_t tmp = 0;
>  
> +	cdclk_state->vco = intel_hpll_vco(dev_priv);
> +
>  	pci_read_config_word(pdev, GCFGC, &tmp);
>  
>  	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
> @@ -263,7 +293,7 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
>  	if (cdclk_sel >= ARRAY_SIZE(div_3200))
>  		goto fail;
>  
> -	switch (vco) {
> +	switch (cdclk_state->vco) {
>  	case 3200000:
>  		div_table = div_3200;
>  		break;
> @@ -277,53 +307,62 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
>  		goto fail;
>  	}
>  
> -	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> +	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
> +					       div_table[cdclk_sel]);
> +	return;
>  
>  fail:
>  	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
> -		  vco, tmp);
> -	return 200000;
> +		  cdclk_state->vco, tmp);
> +	cdclk_state->cdclk = 200000;
>  }
>  
> -static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
> +static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
> +			   struct intel_cdclk_state *cdclk_state)
>  {
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> +	unsigned int cdclk_sel;
>  	uint16_t tmp = 0;
>  
> +	cdclk_state->vco = intel_hpll_vco(dev_priv);
> +
>  	pci_read_config_word(pdev, GCFGC, &tmp);
>  
>  	cdclk_sel = (tmp >> 12) & 0x1;
>  
> -	switch (vco) {
> +	switch (cdclk_state->vco) {
>  	case 2666667:
>  	case 4000000:
>  	case 5333333:
> -		return cdclk_sel ? 333333 : 222222;
> +		cdclk_state->cdclk = cdclk_sel ? 333333 : 222222;
> +		break;
>  	case 3200000:
> -		return cdclk_sel ? 320000 : 228571;
> +		cdclk_state->cdclk = cdclk_sel ? 320000 : 228571;
> +		break;
>  	default:
>  		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
> -			  vco, tmp);
> -		return 222222;
> +			  cdclk_state->vco, tmp);
> +		cdclk_state->cdclk = 222222;
> +		break;
>  	}
>  }
>  
> -static int hsw_get_cdclk(struct drm_i915_private *dev_priv)
> +static void hsw_get_cdclk(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state)
>  {
>  	uint32_t lcpll = I915_READ(LCPLL_CTL);
>  	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
>  
>  	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> -		return 800000;
> +		cdclk_state->cdclk = 800000;
>  	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> -		return 450000;
> +		cdclk_state->cdclk = 450000;
>  	else if (freq == LCPLL_CLK_FREQ_450)
> -		return 450000;
> +		cdclk_state->cdclk = 450000;
>  	else if (IS_HSW_ULT(dev_priv))
> -		return 337500;
> +		cdclk_state->cdclk = 337500;
>  	else
> -		return 540000;
> +		cdclk_state->cdclk = 540000;
>  }
>  
>  static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
> @@ -349,10 +388,13 @@ static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
>  		return 200000;
>  }
>  
> -static int vlv_get_cdclk(struct drm_i915_private *dev_priv)
> +static void vlv_get_cdclk(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state)
>  {
> -	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
> -				      CCK_DISPLAY_CLOCK_CONTROL);
> +	cdclk_state->vco = vlv_get_hpll_vco(dev_priv);
> +	cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
> +					       CCK_DISPLAY_CLOCK_CONTROL,
> +					       cdclk_state->vco);
>  }
>  
>  static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
> @@ -364,7 +406,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
>  	else
>  		default_credits = PFI_CREDIT(8);
>  
> -	if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
> +	if (dev_priv->cdclk.hw.cdclk >= dev_priv->czclk_freq) {
>  		/* CHV suggested value is 31 or 63 */
>  		if (IS_CHERRYVIEW(dev_priv))
>  			credits = PFI_CREDIT_63;
> @@ -396,8 +438,6 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	u32 val, cmd;
>  
> -	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
> -
>  	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
>  		cmd = 2;
>  	else if (cdclk == 266667)
> @@ -461,8 +501,6 @@ static void chv_set_cdclk(struct drm_device *dev, int cdclk)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	u32 val, cmd;
>  
> -	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
> -
>  	switch (cdclk) {
>  	case 333333:
>  	case 320000:
> @@ -508,23 +546,24 @@ static int bdw_calc_cdclk(int max_pixclk)
>  		return 337500;
>  }
>  
> -static int bdw_get_cdclk(struct drm_i915_private *dev_priv)
> +static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state)
>  {
>  	uint32_t lcpll = I915_READ(LCPLL_CTL);
>  	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
>  
>  	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> -		return 800000;
> +		cdclk_state->cdclk = 800000;
>  	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> -		return 450000;
> +		cdclk_state->cdclk = 450000;
>  	else if (freq == LCPLL_CLK_FREQ_450)
> -		return 450000;
> +		cdclk_state->cdclk = 450000;
>  	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
> -		return 540000;
> +		cdclk_state->cdclk = 540000;
>  	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
> -		return 337500;
> +		cdclk_state->cdclk = 337500;
>  	else
> -		return 675000;
> +		cdclk_state->cdclk = 675000;
>  }
>  
>  static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
> @@ -601,9 +640,9 @@ static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
>  
>  	intel_update_cdclk(dev_priv);
>  
> -	WARN(cdclk != dev_priv->cdclk_freq,
> +	WARN(cdclk != dev_priv->cdclk.hw.cdclk,
>  	     "cdclk requested %d kHz but got %d kHz\n",
> -	     cdclk, dev_priv->cdclk_freq);
> +	     cdclk, dev_priv->cdclk.hw.cdclk);
>  }
>  
>  static int skl_calc_cdclk(int max_pixclk, int vco)
> @@ -629,12 +668,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco)
>  	}
>  }
>  
> -static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> +static void skl_dpll0_update(struct drm_i915_private *dev_priv,
> +			     struct intel_cdclk_state *cdclk_state)
>  {
>  	u32 val;
>  
> -	dev_priv->cdclk_pll.ref = 24000;
> -	dev_priv->cdclk_pll.vco = 0;
> +	cdclk_state->ref = 24000;
> +	cdclk_state->vco = 0;
>  
>  	val = I915_READ(LCPLL1_CTL);
>  	if ((val & LCPLL_PLL_ENABLE) == 0)
> @@ -656,11 +696,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
>  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
>  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
>  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
> -		dev_priv->cdclk_pll.vco = 8100000;
> +		cdclk_state->vco = 8100000;
>  		break;
>  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
>  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
> -		dev_priv->cdclk_pll.vco = 8640000;
> +		cdclk_state->vco = 8640000;
>  		break;
>  	default:
>  		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));

This function is a bit funny now, since it sets up the cdclk state based on
current pll0 programming, instead of looking at an atomic state. But so far it
is only used to read the current cdclk, so there's no harm.

> @@ -668,46 +708,57 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
>  	}
>  }
>  
> -static int skl_get_cdclk(struct drm_i915_private *dev_priv)
> +static void skl_get_cdclk(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state)
>  {
>  	u32 cdctl;
>  
> -	skl_dpll0_update(dev_priv);
> +	skl_dpll0_update(dev_priv, cdclk_state);
> +
> +	cdclk_state->cdclk = cdclk_state->ref;
>  
> -	if (dev_priv->cdclk_pll.vco == 0)
> -		return dev_priv->cdclk_pll.ref;
> +	if (cdclk_state->vco == 0)
> +		return;
>  
>  	cdctl = I915_READ(CDCLK_CTL);
>  
> -	if (dev_priv->cdclk_pll.vco == 8640000) {
> +	if (cdclk_state->vco == 8640000) {
>  		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
>  		case CDCLK_FREQ_450_432:
> -			return 432000;
> +			cdclk_state->cdclk = 432000;
> +			break;
>  		case CDCLK_FREQ_337_308:
> -			return 308571;
> +			cdclk_state->cdclk = 308571;
> +			break;
>  		case CDCLK_FREQ_540:
> -			return 540000;
> +			cdclk_state->cdclk = 540000;
> +			break;
>  		case CDCLK_FREQ_675_617:
> -			return 617143;
> +			cdclk_state->cdclk = 617143;
> +			break;
>  		default:
>  			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> +			break;
>  		}
>  	} else {
>  		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
>  		case CDCLK_FREQ_450_432:
> -			return 450000;
> +			cdclk_state->cdclk = 450000;
> +			break;
>  		case CDCLK_FREQ_337_308:
> -			return 337500;
> +			cdclk_state->cdclk = 337500;
> +			break;
>  		case CDCLK_FREQ_540:
> -			return 540000;
> +			cdclk_state->cdclk = 540000;
> +			break;
>  		case CDCLK_FREQ_675_617:
> -			return 675000;
> +			cdclk_state->cdclk = 675000;
> +			break;
>  		default:
>  			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> +			break;
>  		}
>  	}
> -
> -	return dev_priv->cdclk_pll.ref;
>  }
>  
>  /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
> @@ -770,7 +821,7 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
>  				    5))
>  		DRM_ERROR("DPLL0 not locked\n");
>  
> -	dev_priv->cdclk_pll.vco = vco;
> +	dev_priv->cdclk.hw.vco = vco;
>  
>  	/* We'll want to keep using the current vco from now on. */
>  	skl_set_preferred_cdclk_vco(dev_priv, vco);
> @@ -784,7 +835,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
>  				   1))
>  		DRM_ERROR("Couldn't disable DPLL0\n");
>  
> -	dev_priv->cdclk_pll.vco = 0;
> +	dev_priv->cdclk.hw.vco = 0;
>  }
>  
>  static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> @@ -834,11 +885,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
>  		break;
>  	}
>  
> -	if (dev_priv->cdclk_pll.vco != 0 &&
> -	    dev_priv->cdclk_pll.vco != vco)
> +	if (dev_priv->cdclk.hw.vco != 0 &&
> +	    dev_priv->cdclk.hw.vco != vco)
>  		skl_dpll0_disable(dev_priv);
>  
> -	if (dev_priv->cdclk_pll.vco != vco)
> +	if (dev_priv->cdclk.hw.vco != vco)
>  		skl_dpll0_enable(dev_priv, vco);
>  
>  	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
> @@ -866,8 +917,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  
>  	intel_update_cdclk(dev_priv);
>  	/* Is PLL enabled and locked ? */
> -	if (dev_priv->cdclk_pll.vco == 0 ||
> -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> +	if (dev_priv->cdclk.hw.vco == 0 ||
> +	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
>  		goto sanitize;
>  
>  	/* DPLL okay; verify the cdclock
> @@ -878,7 +929,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  	 */
>  	cdctl = I915_READ(CDCLK_CTL);
>  	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
> -		skl_cdclk_decimal(dev_priv->cdclk_freq);
> +		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
>  	if (cdctl == expected)
>  		/* All well; nothing to sanitize */
>  		return;
> @@ -887,14 +938,14 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
>  
>  	/* force cdclk programming */
> -	dev_priv->cdclk_freq = 0;
> +	dev_priv->cdclk.hw.cdclk = 0;
>  	/* force full PLL disable + enable */
> -	dev_priv->cdclk_pll.vco = -1;
> +	dev_priv->cdclk.hw.vco = -1;
>  }
>  
>  void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> +	skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
>  }
>  
>  void skl_init_cdclk(struct drm_i915_private *dev_priv)
> @@ -903,14 +954,15 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
>  
>  	skl_sanitize_cdclk(dev_priv);
>  
> -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
> +	if (dev_priv->cdclk.hw.cdclk != 0 &&
> +	    dev_priv->cdclk.hw.vco != 0) {
>  		/*
>  		 * Use the current vco as our initial
>  		 * guess as to what the preferred vco is.
>  		 */
>  		if (dev_priv->skl_preferred_vco_freq == 0)
>  			skl_set_preferred_cdclk_vco(dev_priv,
> -						    dev_priv->cdclk_pll.vco);
> +						    dev_priv->cdclk.hw.vco);
>  		return;
>  	}
>  
> @@ -950,7 +1002,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
>  {
>  	int ratio;
>  
> -	if (cdclk == dev_priv->cdclk_pll.ref)
> +	if (cdclk == dev_priv->cdclk.hw.ref)
>  		return 0;
>  
>  	switch (cdclk) {
> @@ -967,14 +1019,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
>  		break;
>  	}
>  
> -	return dev_priv->cdclk_pll.ref * ratio;
> +	return dev_priv->cdclk.hw.ref * ratio;
>  }
>  
>  static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
>  {
>  	int ratio;
>  
> -	if (cdclk == dev_priv->cdclk_pll.ref)
> +	if (cdclk == dev_priv->cdclk.hw.ref)
>  		return 0;
>  
>  	switch (cdclk) {
> @@ -987,15 +1039,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
>  		break;
>  	}
>  
> -	return dev_priv->cdclk_pll.ref * ratio;
> +	return dev_priv->cdclk.hw.ref * ratio;
>  }
>  
> -static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> +static void bxt_de_pll_update(struct drm_i915_private *dev_priv,
> +			      struct intel_cdclk_state *cdclk_state)
>  {
>  	u32 val;
>  
> -	dev_priv->cdclk_pll.ref = 19200;
> -	dev_priv->cdclk_pll.vco = 0;
> +	cdclk_state->ref = 19200;
> +	cdclk_state->vco = 0;
>  
>  	val = I915_READ(BXT_DE_PLL_ENABLE);
>  	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
> @@ -1005,20 +1058,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
>  		return;
>  
>  	val = I915_READ(BXT_DE_PLL_CTL);
> -	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
> -		dev_priv->cdclk_pll.ref;
> +	cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
>  }
>  
> -static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
> +static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
> +			  struct intel_cdclk_state *cdclk_state)
>  {
>  	u32 divider;
> -	int div, vco;
> +	int div;
>  
> -	bxt_de_pll_update(dev_priv);
> +	bxt_de_pll_update(dev_priv, cdclk_state);
>  
> -	vco = dev_priv->cdclk_pll.vco;
> -	if (vco == 0)
> -		return dev_priv->cdclk_pll.ref;
> +	cdclk_state->cdclk = cdclk_state->ref;
> +
> +	if (cdclk_state->vco == 0)
> +		return;
>  
>  	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
>  
> @@ -1038,10 +1092,10 @@ static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
>  		break;
>  	default:
>  		MISSING_CASE(divider);
> -		return dev_priv->cdclk_pll.ref;
> +		return;
>  	}
>  
> -	return DIV_ROUND_CLOSEST(vco, div);
> +	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
>  }
>  
>  static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> @@ -1054,12 +1108,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
>  				    1))
>  		DRM_ERROR("timeout waiting for DE PLL unlock\n");
>  
> -	dev_priv->cdclk_pll.vco = 0;
> +	dev_priv->cdclk.hw.vco = 0;
>  }
>  
>  static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
>  {
> -	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
> +	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
>  	u32 val;
>  
>  	val = I915_READ(BXT_DE_PLL_CTL);
> @@ -1077,7 +1131,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
>  				    1))
>  		DRM_ERROR("timeout waiting for DE PLL lock\n");
>  
> -	dev_priv->cdclk_pll.vco = vco;
> +	dev_priv->cdclk.hw.vco = vco;
>  }
>  
>  static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> @@ -1105,7 +1159,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
>  		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
>  		break;
>  	default:
> -		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
> +		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
>  		WARN_ON(vco != 0);
>  
>  		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> @@ -1124,11 +1178,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> -	if (dev_priv->cdclk_pll.vco != 0 &&
> -	    dev_priv->cdclk_pll.vco != vco)
> +	if (dev_priv->cdclk.hw.vco != 0 &&
> +	    dev_priv->cdclk.hw.vco != vco)
>  		bxt_de_pll_disable(dev_priv);
>  
> -	if (dev_priv->cdclk_pll.vco != vco)
> +	if (dev_priv->cdclk.hw.vco != vco)
>  		bxt_de_pll_enable(dev_priv, vco);
>  
>  	val = divider | skl_cdclk_decimal(cdclk);
> @@ -1165,8 +1219,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  
>  	intel_update_cdclk(dev_priv);
>  
> -	if (dev_priv->cdclk_pll.vco == 0 ||
> -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> +	if (dev_priv->cdclk.hw.vco == 0 ||
> +	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
>  		goto sanitize;
>  
>  	/* DPLL okay; verify the cdclock
> @@ -1184,12 +1238,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
>  
>  	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
> -		   skl_cdclk_decimal(dev_priv->cdclk_freq);
> +		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
>  	/*
>  	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
>  	 * enable otherwise.
>  	 */
> -	if (dev_priv->cdclk_freq >= 500000)
> +	if (dev_priv->cdclk.hw.cdclk >= 500000)
>  		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
>  
>  	if (cdctl == expected)
> @@ -1200,10 +1254,10 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
>  
>  	/* force cdclk programming */
> -	dev_priv->cdclk_freq = 0;
> +	dev_priv->cdclk.hw.cdclk = 0;
>  
>  	/* force full PLL disable + enable */
> -	dev_priv->cdclk_pll.vco = -1;
> +	dev_priv->cdclk.hw.vco = -1;
>  }
>  
>  void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> @@ -1212,7 +1266,8 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
>  
>  	bxt_sanitize_cdclk(dev_priv);
>  
> -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
> +	if (dev_priv->cdclk.hw.cdclk != 0 &&
> +	    dev_priv->cdclk.hw.vco != 0)
>  		return;
>  
>  	/*
> @@ -1233,7 +1288,13 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
>  
>  void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> +	bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
> +}
> +
> +bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
> +			       const struct intel_cdclk_state *b)
> +{
> +	return memcmp(a, b, sizeof(*a)) == 0;
>  }
>  
>  static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
> @@ -1533,7 +1594,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
>  		dev_priv->max_cdclk_freq = 400000;
>  	} else {
>  		/* otherwise assume cdclk is fixed */
> -		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
> +		dev_priv->max_cdclk_freq = dev_priv->cdclk.hw.cdclk;
>  	}
>  
>  	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
> @@ -1547,15 +1608,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
>  
>  void intel_update_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
> +	dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw);
>  
> -	if (INTEL_GEN(dev_priv) >= 9)
> -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
> -				 dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
> -				 dev_priv->cdclk_pll.ref);
> -	else
> -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
> -				 dev_priv->cdclk_freq);
> +	DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
> +			 dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco,
> +			 dev_priv->cdclk.hw.ref);
>  
>  	/*
>  	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
> @@ -1565,7 +1622,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv)
>  	 */
>  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>  		I915_WRITE(GMBUSFREQ_VLV,
> -			   DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
> +			   DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000));
>  }
>  
>  static int pch_rawclk(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 519e5d663c5f..6c38ab299506 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -136,7 +136,7 @@ struct intel_limit {
>  };
>  
>  /* returns HPLL frequency in kHz */
> -static int valleyview_get_vco(struct drm_i915_private *dev_priv)
> +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
>  {
>  	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
>  
> @@ -172,7 +172,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
>  			   const char *name, u32 reg)
>  {
>  	if (dev_priv->hpll_freq == 0)
> -		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
> +		dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
>  
>  	return vlv_get_cck_clock(dev_priv, name, reg,
>  				 dev_priv->hpll_freq);
> @@ -12436,7 +12436,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
>  	 */
>  	if (dev_priv->display.modeset_calc_cdclk) {
>  		if (!intel_state->cdclk_pll_vco)
> -			intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco;
> +			intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco;
>  		if (!intel_state->cdclk_pll_vco)
>  			intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
>  
> @@ -12456,8 +12456,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
>  		}
>  
>  		/* All pipes must be switched off while we change the cdclk. */
> -		if (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
> -		    intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) {
> +		if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> +		    intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
>  			ret = intel_modeset_all_pipes(state);
>  			if (ret < 0)
>  				return ret;
> @@ -12874,8 +12874,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>  		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
>  
>  		if (dev_priv->display.modeset_commit_cdclk &&
> -		    (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
> -		     intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco))
> +		    (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> +		     intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
>  			dev_priv->display.modeset_commit_cdclk(state);
>  
>  		/*
> @@ -14724,7 +14724,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
>  
>  	intel_update_cdclk(dev_priv);
>  
> -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
> +	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
>  
>  	intel_init_clock_gating(dev_priv);
>  }
> @@ -14897,7 +14897,7 @@ int intel_modeset_init(struct drm_device *dev)
>  
>  	intel_update_czclk(dev_priv);
>  	intel_update_cdclk(dev_priv);
> -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
> +	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
>  
>  	intel_shared_dpll_init(dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 45ebc9632633..73a708b8d887 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -885,7 +885,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
>  	 * divide by 2000 and use that
>  	 */
>  	if (intel_dig_port->port == PORT_A)
> -		return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
> +		return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000);
>  	else
>  		return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 8d93b7bda3ff..cc0122282a7b 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1225,10 +1225,13 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
>  void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
>  void intel_update_cdclk(struct drm_i915_private *dev_priv);
>  void intel_update_rawclk(struct drm_i915_private *dev_priv);
> +bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
> +			       const struct intel_cdclk_state *b);
>  
>  /* intel_display.c */
>  enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
>  void intel_update_rawclk(struct drm_i915_private *dev_priv);
> +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
>  int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
>  		      const char *name, u32 reg, int ref_freq);
>  int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> index 463056d80f9b..385251e48c74 100644
> --- a/drivers/gpu/drm/i915/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/intel_fbc.c
> @@ -829,7 +829,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
>  
>  	/* WaFbcExceedCdClockThreshold:hsw,bdw */
>  	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
> -	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) {
> +	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) {
>  		fbc->no_fbc_reason = "pixel rate is too big";
>  		return false;
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 1a6ff26dea20..cb50c527401f 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
>  	if (IS_PINEVIEW(dev_priv))
>  		clock = KHz(dev_priv->rawclk_freq);
>  	else
> -		clock = KHz(dev_priv->cdclk_freq);
> +		clock = KHz(dev_priv->cdclk.hw.cdclk);
>  
>  	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
>  }
> @@ -1333,7 +1333,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
>  	if (IS_G4X(dev_priv))
>  		clock = KHz(dev_priv->rawclk_freq);
>  	else
> -		clock = KHz(dev_priv->cdclk_freq);
> +		clock = KHz(dev_priv->cdclk.hw.cdclk);
>  
>  	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 6d5efeb35823..14bbecc8f2ed 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -964,9 +964,12 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
>  static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
>  					  struct i915_power_well *power_well)
>  {
> +	struct intel_cdclk_state cdclk_state = {};
> +
>  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
>  
> -	WARN_ON(dev_priv->cdclk_freq != dev_priv->display.get_cdclk(dev_priv));
> +	dev_priv->display.get_cdclk(dev_priv, &cdclk_state);
> +	WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state));
>  
>  	gen9_assert_dbuf_enabled(dev_priv);
>  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure
  2016-12-22 14:14   ` Ander Conselvan De Oliveira
@ 2016-12-22 14:33     ` Ville Syrjälä
  2016-12-23  9:09       ` Ander Conselvan De Oliveira
  0 siblings, 1 reply; 40+ messages in thread
From: Ville Syrjälä @ 2016-12-22 14:33 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira; +Cc: intel-gfx, Rodrigo Vivi

On Thu, Dec 22, 2016 at 04:14:40PM +0200, Ander Conselvan De Oliveira wrote:
> On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Introduce intel_cdclk state which for now will track the cdclk
> > frequency, the vco frequency and the reference frequency (not sure we
> > want the last one, but I put it there anyway). We'll also make the
> > .get_cdclk() function fill out this state structure rather than
> > just returning the current cdclk frequency.
> > 
> > One immediate benefit is that calling .get_cdclk() will no longer
> > clobber state stored under dev_priv unless ex[plicitly told to do
> 
> Typo: ex[plicity
> 
> > so. Previously it clobbered the vco and reference clocks stored
> > there on some platforms.
> > 
> > We'll expand the use of this structure to actually precomputing the
> > state and whatnot later.
> > 
> > v2: Constify intel_cdclk_state_compare()
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> A couple more comments beloew, but either way,
> 
> Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
> 
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c     |   2 +-
> >  drivers/gpu/drm/i915/i915_drv.h         |  14 +-
> >  drivers/gpu/drm/i915/intel_audio.c      |   2 +-
> >  drivers/gpu/drm/i915/intel_cdclk.c      | 359 ++++++++++++++++++--------------
> >  drivers/gpu/drm/i915/intel_display.c    |  18 +-
> >  drivers/gpu/drm/i915/intel_dp.c         |   2 +-
> >  drivers/gpu/drm/i915/intel_drv.h        |   3 +
> >  drivers/gpu/drm/i915/intel_fbc.c        |   2 +-
> >  drivers/gpu/drm/i915/intel_panel.c      |   4 +-
> >  drivers/gpu/drm/i915/intel_runtime_pm.c |   5 +-
> >  10 files changed, 240 insertions(+), 171 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 15deb2bc568b..c0171eef8f96 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -1235,7 +1235,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
> >  		seq_puts(m, "no P-state info available\n");
> >  	}
> >  
> > -	seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk_freq);
> > +	seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk.hw.cdclk);
> >  	seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
> >  	seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 393b34fb2d1a..a4f1231ff8ca 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -609,9 +609,11 @@ struct intel_initial_plane_config;
> >  struct intel_crtc;
> >  struct intel_limit;
> >  struct dpll;
> > +struct intel_cdclk_state;
> >  
> >  struct drm_i915_display_funcs {
> > -	int (*get_cdclk)(struct drm_i915_private *dev_priv);
> > +	void (*get_cdclk)(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state);
> >  	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
> >  	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
> >  	int (*compute_intermediate_wm)(struct drm_device *dev,
> > @@ -2126,6 +2128,10 @@ struct i915_oa_ops {
> >  	bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv);
> >  };
> >  
> > +struct intel_cdclk_state {
> > +	unsigned int cdclk, vco, ref;
> > +};
> > +
> 
> Maybe document the fields while at it.

Yeah. I guess I should start prinkling in some docs to help newcomers.
Usually I only document things that aren't all that obvious (hardware
fails and whanot). It doesn't help that my brain automatically filters
comments out so that I routinely fail to update them even when they
already exist.


> 
> >  struct drm_i915_private {
> >  	struct drm_device drm;
> >  
> > @@ -2229,7 +2235,7 @@ struct drm_i915_private {
> >  
> >  	unsigned int fsb_freq, mem_freq, is_ddr3;
> >  	unsigned int skl_preferred_vco_freq;
> > -	unsigned int cdclk_freq, max_cdclk_freq;
> > +	unsigned int max_cdclk_freq;
> >  
> >  	/*
> >  	 * For reading holding any crtc lock is sufficient,
> > @@ -2243,8 +2249,8 @@ struct drm_i915_private {
> >  	unsigned int czclk_freq;
> >  
> >  	struct {
> > -		unsigned int vco, ref;
> > -	} cdclk_pll;
> > +		struct intel_cdclk_state hw;
> > +	} cdclk;
> >  
> >  	/**
> >  	 * wq - Driver workqueue for GEM.
> > diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> > index 3bbc96c1767f..a292246995ef 100644
> > --- a/drivers/gpu/drm/i915/intel_audio.c
> > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > @@ -734,7 +734,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
> >  	if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
> >  		return -ENODEV;
> >  
> > -	return dev_priv->cdclk_freq;
> > +	return dev_priv->cdclk.hw.cdclk;
> >  }
> >  
> >  /*
> > diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
> > index 89be610d0879..13c3b5555473 100644
> > --- a/drivers/gpu/drm/i915/intel_cdclk.c
> > +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> > @@ -23,37 +23,44 @@
> >  
> >  #include "intel_drv.h"
> >  
> > -static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv,
> > +				   struct intel_cdclk_state *cdclk_state)
> >  {
> > -	return 133333;
> > +	cdclk_state->cdclk = 133333;
> >  }
> >  
> > -static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv,
> > +				   struct intel_cdclk_state *cdclk_state)
> >  {
> > -	return 200000;
> > +	cdclk_state->cdclk = 200000;
> >  }
> >  
> > -static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv,
> > +				   struct intel_cdclk_state *cdclk_state)
> >  {
> > -	return 266667;
> > +	cdclk_state->cdclk = 266667;
> >  }
> >  
> > -static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv,
> > +				   struct intel_cdclk_state *cdclk_state)
> >  {
> > -	return 333333;
> > +	cdclk_state->cdclk = 333333;
> >  }
> >  
> > -static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv,
> > +				   struct intel_cdclk_state *cdclk_state)
> >  {
> > -	return 400000;
> > +	cdclk_state->cdclk = 400000;
> >  }
> >  
> > -static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
> > +				   struct intel_cdclk_state *cdclk_state)
> >  {
> > -	return 450000;
> > +	cdclk_state->cdclk = 450000;
> >  }
> >  
> > -static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
> > +			   struct intel_cdclk_state *cdclk_state)
> >  {
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> >  	u16 hpllcc = 0;
> > @@ -63,8 +70,10 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> >  	 * encoding is different :(
> >  	 * FIXME is this the right way to detect 852GM/852GMV?
> >  	 */
> > -	if (pdev->revision == 0x1)
> > -		return 133333;
> > +	if (pdev->revision == 0x1) {
> > +		cdclk_state->cdclk = 133333;
> > +		return;
> > +	}
> >  
> >  	pci_bus_read_config_word(pdev->bus,
> >  				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
> > @@ -76,37 +85,43 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> >  	case GC_CLOCK_133_200:
> >  	case GC_CLOCK_133_200_2:
> >  	case GC_CLOCK_100_200:
> > -		return 200000;
> > +		cdclk_state->cdclk = 200000;
> > +		break;
> >  	case GC_CLOCK_166_250:
> > -		return 250000;
> > +		cdclk_state->cdclk = 250000;
> > +		break;
> >  	case GC_CLOCK_100_133:
> > -		return 133333;
> > +		cdclk_state->cdclk = 133333;
> > +		break;
> >  	case GC_CLOCK_133_266:
> >  	case GC_CLOCK_133_266_2:
> >  	case GC_CLOCK_166_266:
> > -		return 266667;
> > +		cdclk_state->cdclk = 266667;
> > +		break;
> >  	}
> > -
> > -	/* Shouldn't happen */
> > -	return 0;
> >  }
> >  
> > -static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
> > +			     struct intel_cdclk_state *cdclk_state)
> >  {
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> >  	u16 gcfgc = 0;
> >  
> >  	pci_read_config_word(pdev, GCFGC, &gcfgc);
> >  
> > -	if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
> > -		return 133333;
> > +	if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
> > +		cdclk_state->cdclk = 133333;
> > +		return;
> > +	}
> >  
> >  	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> >  	case GC_DISPLAY_CLOCK_333_MHZ:
> > -		return 333333;
> > +		cdclk_state->cdclk = 333333;
> > +		break;
> >  	default:
> >  	case GC_DISPLAY_CLOCK_190_200_MHZ:
> > -		return 190000;
> > +		cdclk_state->cdclk = 190000;
> > +		break;
> >  	}
> >  }
> >  
> > @@ -178,7 +193,8 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
> >  	return vco;
> >  }
> >  
> > -static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void g33_get_cdclk(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state)
> >  {
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> >  	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
> > @@ -186,9 +202,11 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> >  	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
> >  	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
> >  	const uint8_t *div_table;
> > -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> > +	unsigned int cdclk_sel;
> >  	uint16_t tmp = 0;
> >  
> > +	cdclk_state->vco = intel_hpll_vco(dev_priv);
> > +
> >  	pci_read_config_word(pdev, GCFGC, &tmp);
> >  
> >  	cdclk_sel = (tmp >> 4) & 0x7;
> > @@ -196,7 +214,7 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> >  	if (cdclk_sel >= ARRAY_SIZE(div_3200))
> >  		goto fail;
> >  
> > -	switch (vco) {
> > +	switch (cdclk_state->vco) {
> >  	case 3200000:
> >  		div_table = div_3200;
> >  		break;
> > @@ -213,15 +231,18 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> >  		goto fail;
> >  	}
> >  
> > -	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> > +	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
> > +					       div_table[cdclk_sel]);
> > +	return;
> >  
> >  fail:
> >  	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
> > -		  vco, tmp);
> > -	return 190476;
> > +		  cdclk_state->vco, tmp);
> > +	cdclk_state->cdclk = 190476;
> >  }
> >  
> > -static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state)
> >  {
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> >  	u16 gcfgc = 0;
> > @@ -230,32 +251,41 @@ static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
> >  
> >  	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> >  	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
> > -		return 266667;
> > +		cdclk_state->cdclk = 266667;
> > +		break;
> >  	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
> > -		return 333333;
> > +		cdclk_state->cdclk = 333333;
> > +		break;
> >  	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
> > -		return 444444;
> > +		cdclk_state->cdclk = 444444;
> > +		break;
> >  	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
> > -		return 200000;
> > +		cdclk_state->cdclk = 200000;
> > +		break;
> >  	default:
> >  		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
> >  	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
> > -		return 133333;
> > +		cdclk_state->cdclk = 133333;
> > +		break;
> >  	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
> > -		return 166667;
> > +		cdclk_state->cdclk = 166667;
> > +		break;
> >  	}
> >  }
> >  
> > -static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
> > +			     struct intel_cdclk_state *cdclk_state)
> >  {
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> >  	static const uint8_t div_3200[] = { 16, 10,  8 };
> >  	static const uint8_t div_4000[] = { 20, 12, 10 };
> >  	static const uint8_t div_5333[] = { 24, 16, 14 };
> >  	const uint8_t *div_table;
> > -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> > +	unsigned int cdclk_sel;
> >  	uint16_t tmp = 0;
> >  
> > +	cdclk_state->vco = intel_hpll_vco(dev_priv);
> > +
> >  	pci_read_config_word(pdev, GCFGC, &tmp);
> >  
> >  	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
> > @@ -263,7 +293,7 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> >  	if (cdclk_sel >= ARRAY_SIZE(div_3200))
> >  		goto fail;
> >  
> > -	switch (vco) {
> > +	switch (cdclk_state->vco) {
> >  	case 3200000:
> >  		div_table = div_3200;
> >  		break;
> > @@ -277,53 +307,62 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> >  		goto fail;
> >  	}
> >  
> > -	return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> > +	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
> > +					       div_table[cdclk_sel]);
> > +	return;
> >  
> >  fail:
> >  	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
> > -		  vco, tmp);
> > -	return 200000;
> > +		  cdclk_state->vco, tmp);
> > +	cdclk_state->cdclk = 200000;
> >  }
> >  
> > -static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
> > +			   struct intel_cdclk_state *cdclk_state)
> >  {
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> > -	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> > +	unsigned int cdclk_sel;
> >  	uint16_t tmp = 0;
> >  
> > +	cdclk_state->vco = intel_hpll_vco(dev_priv);
> > +
> >  	pci_read_config_word(pdev, GCFGC, &tmp);
> >  
> >  	cdclk_sel = (tmp >> 12) & 0x1;
> >  
> > -	switch (vco) {
> > +	switch (cdclk_state->vco) {
> >  	case 2666667:
> >  	case 4000000:
> >  	case 5333333:
> > -		return cdclk_sel ? 333333 : 222222;
> > +		cdclk_state->cdclk = cdclk_sel ? 333333 : 222222;
> > +		break;
> >  	case 3200000:
> > -		return cdclk_sel ? 320000 : 228571;
> > +		cdclk_state->cdclk = cdclk_sel ? 320000 : 228571;
> > +		break;
> >  	default:
> >  		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
> > -			  vco, tmp);
> > -		return 222222;
> > +			  cdclk_state->vco, tmp);
> > +		cdclk_state->cdclk = 222222;
> > +		break;
> >  	}
> >  }
> >  
> > -static int hsw_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void hsw_get_cdclk(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state)
> >  {
> >  	uint32_t lcpll = I915_READ(LCPLL_CTL);
> >  	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> >  
> >  	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> > -		return 800000;
> > +		cdclk_state->cdclk = 800000;
> >  	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> > -		return 450000;
> > +		cdclk_state->cdclk = 450000;
> >  	else if (freq == LCPLL_CLK_FREQ_450)
> > -		return 450000;
> > +		cdclk_state->cdclk = 450000;
> >  	else if (IS_HSW_ULT(dev_priv))
> > -		return 337500;
> > +		cdclk_state->cdclk = 337500;
> >  	else
> > -		return 540000;
> > +		cdclk_state->cdclk = 540000;
> >  }
> >  
> >  static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
> > @@ -349,10 +388,13 @@ static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
> >  		return 200000;
> >  }
> >  
> > -static int vlv_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void vlv_get_cdclk(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state)
> >  {
> > -	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
> > -				      CCK_DISPLAY_CLOCK_CONTROL);
> > +	cdclk_state->vco = vlv_get_hpll_vco(dev_priv);
> > +	cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
> > +					       CCK_DISPLAY_CLOCK_CONTROL,
> > +					       cdclk_state->vco);
> >  }
> >  
> >  static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
> > @@ -364,7 +406,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
> >  	else
> >  		default_credits = PFI_CREDIT(8);
> >  
> > -	if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
> > +	if (dev_priv->cdclk.hw.cdclk >= dev_priv->czclk_freq) {
> >  		/* CHV suggested value is 31 or 63 */
> >  		if (IS_CHERRYVIEW(dev_priv))
> >  			credits = PFI_CREDIT_63;
> > @@ -396,8 +438,6 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	u32 val, cmd;
> >  
> > -	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
> > -
> >  	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
> >  		cmd = 2;
> >  	else if (cdclk == 266667)
> > @@ -461,8 +501,6 @@ static void chv_set_cdclk(struct drm_device *dev, int cdclk)
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	u32 val, cmd;
> >  
> > -	WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq);
> > -
> >  	switch (cdclk) {
> >  	case 333333:
> >  	case 320000:
> > @@ -508,23 +546,24 @@ static int bdw_calc_cdclk(int max_pixclk)
> >  		return 337500;
> >  }
> >  
> > -static int bdw_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state)
> >  {
> >  	uint32_t lcpll = I915_READ(LCPLL_CTL);
> >  	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> >  
> >  	if (lcpll & LCPLL_CD_SOURCE_FCLK)
> > -		return 800000;
> > +		cdclk_state->cdclk = 800000;
> >  	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> > -		return 450000;
> > +		cdclk_state->cdclk = 450000;
> >  	else if (freq == LCPLL_CLK_FREQ_450)
> > -		return 450000;
> > +		cdclk_state->cdclk = 450000;
> >  	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
> > -		return 540000;
> > +		cdclk_state->cdclk = 540000;
> >  	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
> > -		return 337500;
> > +		cdclk_state->cdclk = 337500;
> >  	else
> > -		return 675000;
> > +		cdclk_state->cdclk = 675000;
> >  }
> >  
> >  static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
> > @@ -601,9 +640,9 @@ static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
> >  
> >  	intel_update_cdclk(dev_priv);
> >  
> > -	WARN(cdclk != dev_priv->cdclk_freq,
> > +	WARN(cdclk != dev_priv->cdclk.hw.cdclk,
> >  	     "cdclk requested %d kHz but got %d kHz\n",
> > -	     cdclk, dev_priv->cdclk_freq);
> > +	     cdclk, dev_priv->cdclk.hw.cdclk);
> >  }
> >  
> >  static int skl_calc_cdclk(int max_pixclk, int vco)
> > @@ -629,12 +668,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco)
> >  	}
> >  }
> >  
> > -static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> > +static void skl_dpll0_update(struct drm_i915_private *dev_priv,
> > +			     struct intel_cdclk_state *cdclk_state)
> >  {
> >  	u32 val;
> >  
> > -	dev_priv->cdclk_pll.ref = 24000;
> > -	dev_priv->cdclk_pll.vco = 0;
> > +	cdclk_state->ref = 24000;
> > +	cdclk_state->vco = 0;
> >  
> >  	val = I915_READ(LCPLL1_CTL);
> >  	if ((val & LCPLL_PLL_ENABLE) == 0)
> > @@ -656,11 +696,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
> >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
> >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
> > -		dev_priv->cdclk_pll.vco = 8100000;
> > +		cdclk_state->vco = 8100000;
> >  		break;
> >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
> >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
> > -		dev_priv->cdclk_pll.vco = 8640000;
> > +		cdclk_state->vco = 8640000;
> >  		break;
> >  	default:
> >  		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> 
> This function is a bit funny now, since it sets up the cdclk state based on
> current pll0 programming, instead of looking at an atomic state.

We should probably rename it to somehting more descriptive. skl_get_dpll0()
maybe. Or maybe skl_dpll0_get_config to match the .get_config()
nomenclature used for eg. encoders. Though if we go there then
.get_cdclk() might need to be renamed to .cdclk_get_config or something.

> But so far it
> is only used to read the current cdclk, so there's no harm.
> 
> > @@ -668,46 +708,57 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> >  	}
> >  }
> >  
> > -static int skl_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void skl_get_cdclk(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state)
> >  {
> >  	u32 cdctl;
> >  
> > -	skl_dpll0_update(dev_priv);
> > +	skl_dpll0_update(dev_priv, cdclk_state);
> > +
> > +	cdclk_state->cdclk = cdclk_state->ref;
> >  
> > -	if (dev_priv->cdclk_pll.vco == 0)
> > -		return dev_priv->cdclk_pll.ref;
> > +	if (cdclk_state->vco == 0)
> > +		return;
> >  
> >  	cdctl = I915_READ(CDCLK_CTL);
> >  
> > -	if (dev_priv->cdclk_pll.vco == 8640000) {
> > +	if (cdclk_state->vco == 8640000) {
> >  		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> >  		case CDCLK_FREQ_450_432:
> > -			return 432000;
> > +			cdclk_state->cdclk = 432000;
> > +			break;
> >  		case CDCLK_FREQ_337_308:
> > -			return 308571;
> > +			cdclk_state->cdclk = 308571;
> > +			break;
> >  		case CDCLK_FREQ_540:
> > -			return 540000;
> > +			cdclk_state->cdclk = 540000;
> > +			break;
> >  		case CDCLK_FREQ_675_617:
> > -			return 617143;
> > +			cdclk_state->cdclk = 617143;
> > +			break;
> >  		default:
> >  			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> > +			break;
> >  		}
> >  	} else {
> >  		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> >  		case CDCLK_FREQ_450_432:
> > -			return 450000;
> > +			cdclk_state->cdclk = 450000;
> > +			break;
> >  		case CDCLK_FREQ_337_308:
> > -			return 337500;
> > +			cdclk_state->cdclk = 337500;
> > +			break;
> >  		case CDCLK_FREQ_540:
> > -			return 540000;
> > +			cdclk_state->cdclk = 540000;
> > +			break;
> >  		case CDCLK_FREQ_675_617:
> > -			return 675000;
> > +			cdclk_state->cdclk = 675000;
> > +			break;
> >  		default:
> >  			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> > +			break;
> >  		}
> >  	}
> > -
> > -	return dev_priv->cdclk_pll.ref;
> >  }
> >  
> >  /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
> > @@ -770,7 +821,7 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
> >  				    5))
> >  		DRM_ERROR("DPLL0 not locked\n");
> >  
> > -	dev_priv->cdclk_pll.vco = vco;
> > +	dev_priv->cdclk.hw.vco = vco;
> >  
> >  	/* We'll want to keep using the current vco from now on. */
> >  	skl_set_preferred_cdclk_vco(dev_priv, vco);
> > @@ -784,7 +835,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
> >  				   1))
> >  		DRM_ERROR("Couldn't disable DPLL0\n");
> >  
> > -	dev_priv->cdclk_pll.vco = 0;
> > +	dev_priv->cdclk.hw.vco = 0;
> >  }
> >  
> >  static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> > @@ -834,11 +885,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> >  		break;
> >  	}
> >  
> > -	if (dev_priv->cdclk_pll.vco != 0 &&
> > -	    dev_priv->cdclk_pll.vco != vco)
> > +	if (dev_priv->cdclk.hw.vco != 0 &&
> > +	    dev_priv->cdclk.hw.vco != vco)
> >  		skl_dpll0_disable(dev_priv);
> >  
> > -	if (dev_priv->cdclk_pll.vco != vco)
> > +	if (dev_priv->cdclk.hw.vco != vco)
> >  		skl_dpll0_enable(dev_priv, vco);
> >  
> >  	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
> > @@ -866,8 +917,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> >  
> >  	intel_update_cdclk(dev_priv);
> >  	/* Is PLL enabled and locked ? */
> > -	if (dev_priv->cdclk_pll.vco == 0 ||
> > -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> > +	if (dev_priv->cdclk.hw.vco == 0 ||
> > +	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
> >  		goto sanitize;
> >  
> >  	/* DPLL okay; verify the cdclock
> > @@ -878,7 +929,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> >  	 */
> >  	cdctl = I915_READ(CDCLK_CTL);
> >  	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
> > -		skl_cdclk_decimal(dev_priv->cdclk_freq);
> > +		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
> >  	if (cdctl == expected)
> >  		/* All well; nothing to sanitize */
> >  		return;
> > @@ -887,14 +938,14 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> >  	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> >  
> >  	/* force cdclk programming */
> > -	dev_priv->cdclk_freq = 0;
> > +	dev_priv->cdclk.hw.cdclk = 0;
> >  	/* force full PLL disable + enable */
> > -	dev_priv->cdclk_pll.vco = -1;
> > +	dev_priv->cdclk.hw.vco = -1;
> >  }
> >  
> >  void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
> >  {
> > -	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> > +	skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
> >  }
> >  
> >  void skl_init_cdclk(struct drm_i915_private *dev_priv)
> > @@ -903,14 +954,15 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
> >  
> >  	skl_sanitize_cdclk(dev_priv);
> >  
> > -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
> > +	if (dev_priv->cdclk.hw.cdclk != 0 &&
> > +	    dev_priv->cdclk.hw.vco != 0) {
> >  		/*
> >  		 * Use the current vco as our initial
> >  		 * guess as to what the preferred vco is.
> >  		 */
> >  		if (dev_priv->skl_preferred_vco_freq == 0)
> >  			skl_set_preferred_cdclk_vco(dev_priv,
> > -						    dev_priv->cdclk_pll.vco);
> > +						    dev_priv->cdclk.hw.vco);
> >  		return;
> >  	}
> >  
> > @@ -950,7 +1002,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> >  {
> >  	int ratio;
> >  
> > -	if (cdclk == dev_priv->cdclk_pll.ref)
> > +	if (cdclk == dev_priv->cdclk.hw.ref)
> >  		return 0;
> >  
> >  	switch (cdclk) {
> > @@ -967,14 +1019,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> >  		break;
> >  	}
> >  
> > -	return dev_priv->cdclk_pll.ref * ratio;
> > +	return dev_priv->cdclk.hw.ref * ratio;
> >  }
> >  
> >  static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> >  {
> >  	int ratio;
> >  
> > -	if (cdclk == dev_priv->cdclk_pll.ref)
> > +	if (cdclk == dev_priv->cdclk.hw.ref)
> >  		return 0;
> >  
> >  	switch (cdclk) {
> > @@ -987,15 +1039,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> >  		break;
> >  	}
> >  
> > -	return dev_priv->cdclk_pll.ref * ratio;
> > +	return dev_priv->cdclk.hw.ref * ratio;
> >  }
> >  
> > -static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> > +static void bxt_de_pll_update(struct drm_i915_private *dev_priv,
> > +			      struct intel_cdclk_state *cdclk_state)
> >  {
> >  	u32 val;
> >  
> > -	dev_priv->cdclk_pll.ref = 19200;
> > -	dev_priv->cdclk_pll.vco = 0;
> > +	cdclk_state->ref = 19200;
> > +	cdclk_state->vco = 0;
> >  
> >  	val = I915_READ(BXT_DE_PLL_ENABLE);
> >  	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
> > @@ -1005,20 +1058,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> >  		return;
> >  
> >  	val = I915_READ(BXT_DE_PLL_CTL);
> > -	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
> > -		dev_priv->cdclk_pll.ref;
> > +	cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
> >  }
> >  
> > -static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
> > +static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
> > +			  struct intel_cdclk_state *cdclk_state)
> >  {
> >  	u32 divider;
> > -	int div, vco;
> > +	int div;
> >  
> > -	bxt_de_pll_update(dev_priv);
> > +	bxt_de_pll_update(dev_priv, cdclk_state);
> >  
> > -	vco = dev_priv->cdclk_pll.vco;
> > -	if (vco == 0)
> > -		return dev_priv->cdclk_pll.ref;
> > +	cdclk_state->cdclk = cdclk_state->ref;
> > +
> > +	if (cdclk_state->vco == 0)
> > +		return;
> >  
> >  	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
> >  
> > @@ -1038,10 +1092,10 @@ static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
> >  		break;
> >  	default:
> >  		MISSING_CASE(divider);
> > -		return dev_priv->cdclk_pll.ref;
> > +		return;
> >  	}
> >  
> > -	return DIV_ROUND_CLOSEST(vco, div);
> > +	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
> >  }
> >  
> >  static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> > @@ -1054,12 +1108,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> >  				    1))
> >  		DRM_ERROR("timeout waiting for DE PLL unlock\n");
> >  
> > -	dev_priv->cdclk_pll.vco = 0;
> > +	dev_priv->cdclk.hw.vco = 0;
> >  }
> >  
> >  static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
> >  {
> > -	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
> > +	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
> >  	u32 val;
> >  
> >  	val = I915_READ(BXT_DE_PLL_CTL);
> > @@ -1077,7 +1131,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
> >  				    1))
> >  		DRM_ERROR("timeout waiting for DE PLL lock\n");
> >  
> > -	dev_priv->cdclk_pll.vco = vco;
> > +	dev_priv->cdclk.hw.vco = vco;
> >  }
> >  
> >  static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> > @@ -1105,7 +1159,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> >  		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> >  		break;
> >  	default:
> > -		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
> > +		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
> >  		WARN_ON(vco != 0);
> >  
> >  		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> > @@ -1124,11 +1178,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> >  		return;
> >  	}
> >  
> > -	if (dev_priv->cdclk_pll.vco != 0 &&
> > -	    dev_priv->cdclk_pll.vco != vco)
> > +	if (dev_priv->cdclk.hw.vco != 0 &&
> > +	    dev_priv->cdclk.hw.vco != vco)
> >  		bxt_de_pll_disable(dev_priv);
> >  
> > -	if (dev_priv->cdclk_pll.vco != vco)
> > +	if (dev_priv->cdclk.hw.vco != vco)
> >  		bxt_de_pll_enable(dev_priv, vco);
> >  
> >  	val = divider | skl_cdclk_decimal(cdclk);
> > @@ -1165,8 +1219,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> >  
> >  	intel_update_cdclk(dev_priv);
> >  
> > -	if (dev_priv->cdclk_pll.vco == 0 ||
> > -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> > +	if (dev_priv->cdclk.hw.vco == 0 ||
> > +	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
> >  		goto sanitize;
> >  
> >  	/* DPLL okay; verify the cdclock
> > @@ -1184,12 +1238,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> >  	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
> >  
> >  	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
> > -		   skl_cdclk_decimal(dev_priv->cdclk_freq);
> > +		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
> >  	/*
> >  	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
> >  	 * enable otherwise.
> >  	 */
> > -	if (dev_priv->cdclk_freq >= 500000)
> > +	if (dev_priv->cdclk.hw.cdclk >= 500000)
> >  		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> >  
> >  	if (cdctl == expected)
> > @@ -1200,10 +1254,10 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> >  	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> >  
> >  	/* force cdclk programming */
> > -	dev_priv->cdclk_freq = 0;
> > +	dev_priv->cdclk.hw.cdclk = 0;
> >  
> >  	/* force full PLL disable + enable */
> > -	dev_priv->cdclk_pll.vco = -1;
> > +	dev_priv->cdclk.hw.vco = -1;
> >  }
> >  
> >  void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> > @@ -1212,7 +1266,8 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> >  
> >  	bxt_sanitize_cdclk(dev_priv);
> >  
> > -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
> > +	if (dev_priv->cdclk.hw.cdclk != 0 &&
> > +	    dev_priv->cdclk.hw.vco != 0)
> >  		return;
> >  
> >  	/*
> > @@ -1233,7 +1288,13 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> >  
> >  void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
> >  {
> > -	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> > +	bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
> > +}
> > +
> > +bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
> > +			       const struct intel_cdclk_state *b)
> > +{
> > +	return memcmp(a, b, sizeof(*a)) == 0;
> >  }
> >  
> >  static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
> > @@ -1533,7 +1594,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> >  		dev_priv->max_cdclk_freq = 400000;
> >  	} else {
> >  		/* otherwise assume cdclk is fixed */
> > -		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
> > +		dev_priv->max_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> >  	}
> >  
> >  	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
> > @@ -1547,15 +1608,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> >  
> >  void intel_update_cdclk(struct drm_i915_private *dev_priv)
> >  {
> > -	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
> > +	dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw);
> >  
> > -	if (INTEL_GEN(dev_priv) >= 9)
> > -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
> > -				 dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
> > -				 dev_priv->cdclk_pll.ref);
> > -	else
> > -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
> > -				 dev_priv->cdclk_freq);
> > +	DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
> > +			 dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco,
> > +			 dev_priv->cdclk.hw.ref);
> >  
> >  	/*
> >  	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
> > @@ -1565,7 +1622,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv)
> >  	 */
> >  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >  		I915_WRITE(GMBUSFREQ_VLV,
> > -			   DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
> > +			   DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000));
> >  }
> >  
> >  static int pch_rawclk(struct drm_i915_private *dev_priv)
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 519e5d663c5f..6c38ab299506 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -136,7 +136,7 @@ struct intel_limit {
> >  };
> >  
> >  /* returns HPLL frequency in kHz */
> > -static int valleyview_get_vco(struct drm_i915_private *dev_priv)
> > +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
> >  {
> >  	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
> >  
> > @@ -172,7 +172,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> >  			   const char *name, u32 reg)
> >  {
> >  	if (dev_priv->hpll_freq == 0)
> > -		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
> > +		dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
> >  
> >  	return vlv_get_cck_clock(dev_priv, name, reg,
> >  				 dev_priv->hpll_freq);
> > @@ -12436,7 +12436,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
> >  	 */
> >  	if (dev_priv->display.modeset_calc_cdclk) {
> >  		if (!intel_state->cdclk_pll_vco)
> > -			intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco;
> > +			intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco;
> >  		if (!intel_state->cdclk_pll_vco)
> >  			intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
> >  
> > @@ -12456,8 +12456,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
> >  		}
> >  
> >  		/* All pipes must be switched off while we change the cdclk. */
> > -		if (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
> > -		    intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) {
> > +		if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> > +		    intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
> >  			ret = intel_modeset_all_pipes(state);
> >  			if (ret < 0)
> >  				return ret;
> > @@ -12874,8 +12874,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> >  		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
> >  
> >  		if (dev_priv->display.modeset_commit_cdclk &&
> > -		    (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
> > -		     intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco))
> > +		    (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> > +		     intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
> >  			dev_priv->display.modeset_commit_cdclk(state);
> >  
> >  		/*
> > @@ -14724,7 +14724,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
> >  
> >  	intel_update_cdclk(dev_priv);
> >  
> > -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
> > +	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> >  
> >  	intel_init_clock_gating(dev_priv);
> >  }
> > @@ -14897,7 +14897,7 @@ int intel_modeset_init(struct drm_device *dev)
> >  
> >  	intel_update_czclk(dev_priv);
> >  	intel_update_cdclk(dev_priv);
> > -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
> > +	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> >  
> >  	intel_shared_dpll_init(dev);
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 45ebc9632633..73a708b8d887 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -885,7 +885,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
> >  	 * divide by 2000 and use that
> >  	 */
> >  	if (intel_dig_port->port == PORT_A)
> > -		return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
> > +		return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000);
> >  	else
> >  		return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
> >  }
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 8d93b7bda3ff..cc0122282a7b 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1225,10 +1225,13 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
> >  void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
> >  void intel_update_cdclk(struct drm_i915_private *dev_priv);
> >  void intel_update_rawclk(struct drm_i915_private *dev_priv);
> > +bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
> > +			       const struct intel_cdclk_state *b);
> >  
> >  /* intel_display.c */
> >  enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
> >  void intel_update_rawclk(struct drm_i915_private *dev_priv);
> > +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
> >  int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
> >  		      const char *name, u32 reg, int ref_freq);
> >  int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> > diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> > index 463056d80f9b..385251e48c74 100644
> > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > @@ -829,7 +829,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
> >  
> >  	/* WaFbcExceedCdClockThreshold:hsw,bdw */
> >  	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
> > -	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) {
> > +	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) {
> >  		fbc->no_fbc_reason = "pixel rate is too big";
> >  		return false;
> >  	}
> > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > index 1a6ff26dea20..cb50c527401f 100644
> > --- a/drivers/gpu/drm/i915/intel_panel.c
> > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > @@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> >  	if (IS_PINEVIEW(dev_priv))
> >  		clock = KHz(dev_priv->rawclk_freq);
> >  	else
> > -		clock = KHz(dev_priv->cdclk_freq);
> > +		clock = KHz(dev_priv->cdclk.hw.cdclk);
> >  
> >  	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
> >  }
> > @@ -1333,7 +1333,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> >  	if (IS_G4X(dev_priv))
> >  		clock = KHz(dev_priv->rawclk_freq);
> >  	else
> > -		clock = KHz(dev_priv->cdclk_freq);
> > +		clock = KHz(dev_priv->cdclk.hw.cdclk);
> >  
> >  	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
> >  }
> > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > index 6d5efeb35823..14bbecc8f2ed 100644
> > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > @@ -964,9 +964,12 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
> >  static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
> >  					  struct i915_power_well *power_well)
> >  {
> > +	struct intel_cdclk_state cdclk_state = {};
> > +
> >  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
> >  
> > -	WARN_ON(dev_priv->cdclk_freq != dev_priv->display.get_cdclk(dev_priv));
> > +	dev_priv->display.get_cdclk(dev_priv, &cdclk_state);
> > +	WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state));
> >  
> >  	gen9_assert_dbuf_enabled(dev_priv);
> >  

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

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

* Re: [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure
  2016-12-22 14:33     ` Ville Syrjälä
@ 2016-12-23  9:09       ` Ander Conselvan De Oliveira
  2016-12-23 12:27         ` Ville Syrjälä
  0 siblings, 1 reply; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23  9:09 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Rodrigo Vivi

On Thu, 2016-12-22 at 16:33 +0200, Ville Syrjälä wrote:
> On Thu, Dec 22, 2016 at 04:14:40PM +0200, Ander Conselvan De Oliveira wrote:
> > 
> > On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > > 
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Introduce intel_cdclk state which for now will track the cdclk
> > > frequency, the vco frequency and the reference frequency (not sure we
> > > want the last one, but I put it there anyway). We'll also make the
> > > .get_cdclk() function fill out this state structure rather than
> > > just returning the current cdclk frequency.
> > > 
> > > One immediate benefit is that calling .get_cdclk() will no longer
> > > clobber state stored under dev_priv unless ex[plicitly told to do
> > Typo: ex[plicity
> > 
> > > 
> > > so. Previously it clobbered the vco and reference clocks stored
> > > there on some platforms.
> > > 
> > > We'll expand the use of this structure to actually precomputing the
> > > state and whatnot later.
> > > 
> > > v2: Constify intel_cdclk_state_compare()
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > A couple more comments beloew, but either way,
> > 
> > Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
> > 
> > > 
> > > ---
> > >  drivers/gpu/drm/i915/i915_debugfs.c     |   2 +-
> > >  drivers/gpu/drm/i915/i915_drv.h         |  14 +-
> > >  drivers/gpu/drm/i915/intel_audio.c      |   2 +-
> > >  drivers/gpu/drm/i915/intel_cdclk.c      | 359 ++++++++++++++++++--------------
> > >  drivers/gpu/drm/i915/intel_display.c    |  18 +-
> > >  drivers/gpu/drm/i915/intel_dp.c         |   2 +-
> > >  drivers/gpu/drm/i915/intel_drv.h        |   3 +
> > >  drivers/gpu/drm/i915/intel_fbc.c        |   2 +-
> > >  drivers/gpu/drm/i915/intel_panel.c      |   4 +-
> > >  drivers/gpu/drm/i915/intel_runtime_pm.c |   5 +-
> > >  10 files changed, 240 insertions(+), 171 deletions(-)
> > > 

[...]

@@ -629,12 +668,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco)
> > >  }
> > >  
> > > -static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> > > +static void skl_dpll0_update(struct drm_i915_private *dev_priv,
> > > +			     struct intel_cdclk_state *cdclk_state)
> > >  {
> > >  	u32 val;
> > >  
> > > -	dev_priv->cdclk_pll.ref = 24000;
> > > -	dev_priv->cdclk_pll.vco = 0;
> > > +	cdclk_state->ref = 24000;
> > > +	cdclk_state->vco = 0;
> > >  
> > >  	val = I915_READ(LCPLL1_CTL);
> > >  	if ((val & LCPLL_PLL_ENABLE) == 0)
> > > @@ -656,11 +696,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
> > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
> > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
> > > -		dev_priv->cdclk_pll.vco = 8100000;
> > > +		cdclk_state->vco = 8100000;
> > >  		break;
> > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
> > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
> > > -		dev_priv->cdclk_pll.vco = 8640000;
> > > +		cdclk_state->vco = 8640000;
> > >  		break;
> > >  	default:
> > >  		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> > This function is a bit funny now, since it sets up the cdclk state based on
> > current pll0 programming, instead of looking at an atomic state.
> We should probably rename it to somehting more descriptive. skl_get_dpll0()
> maybe. Or maybe skl_dpll0_get_config to match the .get_config()
> nomenclature used for eg. encoders.

Hmm, I think the problem is that this have a mix of get_hw_state() and
get_config(). We actually have skl_ddi_dpll0_get_hw_state(), but it wouldn't be
trivial to make that code reusable for the cdclk stuff.

Maybe it should be two separate functions, one that gets the hardware state and
another for choosing the vco. Then

  vco = skl_cdclk_vco(skl_dpll0_get_hw_state());

directly in skl_get_cdclk() ? I'm not really sure, maybe just leave the way it
is for now.

>  Though if we go there then
> .get_cdclk() might need to be renamed to .cdclk_get_config or something.

.cdclk_get_hw_state() ?


Ander

> 
> > 
> > But so far it
> > is only used to read the current cdclk, so there's no harm.
> > 
> > > 
> > > @@ -668,46 +708,57 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> > >  	}
> > >  }
> > >  
> > > -static int skl_get_cdclk(struct drm_i915_private *dev_priv)
> > > +static void skl_get_cdclk(struct drm_i915_private *dev_priv,
> > > +			  struct intel_cdclk_state *cdclk_state)
> > >  {
> > >  	u32 cdctl;
> > >  
> > > -	skl_dpll0_update(dev_priv);
> > > +	skl_dpll0_update(dev_priv, cdclk_state);
> > > +
> > > +	cdclk_state->cdclk = cdclk_state->ref;
> > >  
> > > -	if (dev_priv->cdclk_pll.vco == 0)
> > > -		return dev_priv->cdclk_pll.ref;
> > > +	if (cdclk_state->vco == 0)
> > > +		return;
> > >  
> > >  	cdctl = I915_READ(CDCLK_CTL);
> > >  
> > > -	if (dev_priv->cdclk_pll.vco == 8640000) {
> > > +	if (cdclk_state->vco == 8640000) {
> > >  		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> > >  		case CDCLK_FREQ_450_432:
> > > -			return 432000;
> > > +			cdclk_state->cdclk = 432000;
> > > +			break;
> > >  		case CDCLK_FREQ_337_308:
> > > -			return 308571;
> > > +			cdclk_state->cdclk = 308571;
> > > +			break;
> > >  		case CDCLK_FREQ_540:
> > > -			return 540000;
> > > +			cdclk_state->cdclk = 540000;
> > > +			break;
> > >  		case CDCLK_FREQ_675_617:
> > > -			return 617143;
> > > +			cdclk_state->cdclk = 617143;
> > > +			break;
> > >  		default:
> > >  			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> > > +			break;
> > >  		}
> > >  	} else {
> > >  		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> > >  		case CDCLK_FREQ_450_432:
> > > -			return 450000;
> > > +			cdclk_state->cdclk = 450000;
> > > +			break;
> > >  		case CDCLK_FREQ_337_308:
> > > -			return 337500;
> > > +			cdclk_state->cdclk = 337500;
> > > +			break;
> > >  		case CDCLK_FREQ_540:
> > > -			return 540000;
> > > +			cdclk_state->cdclk = 540000;
> > > +			break;
> > >  		case CDCLK_FREQ_675_617:
> > > -			return 675000;
> > > +			cdclk_state->cdclk = 675000;
> > > +			break;
> > >  		default:
> > >  			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> > > +			break;
> > >  		}
> > >  	}
> > > -
> > > -	return dev_priv->cdclk_pll.ref;
> > >  }
> > >  
> > >  /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
> > > @@ -770,7 +821,7 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
> > >  				    5))
> > >  		DRM_ERROR("DPLL0 not locked\n");
> > >  
> > > -	dev_priv->cdclk_pll.vco = vco;
> > > +	dev_priv->cdclk.hw.vco = vco;
> > >  
> > >  	/* We'll want to keep using the current vco from now on. */
> > >  	skl_set_preferred_cdclk_vco(dev_priv, vco);
> > > @@ -784,7 +835,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
> > >  				   1))
> > >  		DRM_ERROR("Couldn't disable DPLL0\n");
> > >  
> > > -	dev_priv->cdclk_pll.vco = 0;
> > > +	dev_priv->cdclk.hw.vco = 0;
> > >  }
> > >  
> > >  static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> > > @@ -834,11 +885,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> > >  		break;
> > >  	}
> > >  
> > > -	if (dev_priv->cdclk_pll.vco != 0 &&
> > > -	    dev_priv->cdclk_pll.vco != vco)
> > > +	if (dev_priv->cdclk.hw.vco != 0 &&
> > > +	    dev_priv->cdclk.hw.vco != vco)
> > >  		skl_dpll0_disable(dev_priv);
> > >  
> > > -	if (dev_priv->cdclk_pll.vco != vco)
> > > +	if (dev_priv->cdclk.hw.vco != vco)
> > >  		skl_dpll0_enable(dev_priv, vco);
> > >  
> > >  	I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
> > > @@ -866,8 +917,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> > >  
> > >  	intel_update_cdclk(dev_priv);
> > >  	/* Is PLL enabled and locked ? */
> > > -	if (dev_priv->cdclk_pll.vco == 0 ||
> > > -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> > > +	if (dev_priv->cdclk.hw.vco == 0 ||
> > > +	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
> > >  		goto sanitize;
> > >  
> > >  	/* DPLL okay; verify the cdclock
> > > @@ -878,7 +929,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> > >  	 */
> > >  	cdctl = I915_READ(CDCLK_CTL);
> > >  	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
> > > -		skl_cdclk_decimal(dev_priv->cdclk_freq);
> > > +		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
> > >  	if (cdctl == expected)
> > >  		/* All well; nothing to sanitize */
> > >  		return;
> > > @@ -887,14 +938,14 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> > >  	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> > >  
> > >  	/* force cdclk programming */
> > > -	dev_priv->cdclk_freq = 0;
> > > +	dev_priv->cdclk.hw.cdclk = 0;
> > >  	/* force full PLL disable + enable */
> > > -	dev_priv->cdclk_pll.vco = -1;
> > > +	dev_priv->cdclk.hw.vco = -1;
> > >  }
> > >  
> > >  void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
> > >  {
> > > -	skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> > > +	skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
> > >  }
> > >  
> > >  void skl_init_cdclk(struct drm_i915_private *dev_priv)
> > > @@ -903,14 +954,15 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
> > >  
> > >  	skl_sanitize_cdclk(dev_priv);
> > >  
> > > -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
> > > +	if (dev_priv->cdclk.hw.cdclk != 0 &&
> > > +	    dev_priv->cdclk.hw.vco != 0) {
> > >  		/*
> > >  		 * Use the current vco as our initial
> > >  		 * guess as to what the preferred vco is.
> > >  		 */
> > >  		if (dev_priv->skl_preferred_vco_freq == 0)
> > >  			skl_set_preferred_cdclk_vco(dev_priv,
> > > -						    dev_priv->cdclk_pll.vco);
> > > +						    dev_priv->cdclk.hw.vco);
> > >  		return;
> > >  	}
> > >  
> > > @@ -950,7 +1002,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> > >  {
> > >  	int ratio;
> > >  
> > > -	if (cdclk == dev_priv->cdclk_pll.ref)
> > > +	if (cdclk == dev_priv->cdclk.hw.ref)
> > >  		return 0;
> > >  
> > >  	switch (cdclk) {
> > > @@ -967,14 +1019,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> > >  		break;
> > >  	}
> > >  
> > > -	return dev_priv->cdclk_pll.ref * ratio;
> > > +	return dev_priv->cdclk.hw.ref * ratio;
> > >  }
> > >  
> > >  static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> > >  {
> > >  	int ratio;
> > >  
> > > -	if (cdclk == dev_priv->cdclk_pll.ref)
> > > +	if (cdclk == dev_priv->cdclk.hw.ref)
> > >  		return 0;
> > >  
> > >  	switch (cdclk) {
> > > @@ -987,15 +1039,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> > >  		break;
> > >  	}
> > >  
> > > -	return dev_priv->cdclk_pll.ref * ratio;
> > > +	return dev_priv->cdclk.hw.ref * ratio;
> > >  }
> > >  
> > > -static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> > > +static void bxt_de_pll_update(struct drm_i915_private *dev_priv,
> > > +			      struct intel_cdclk_state *cdclk_state)
> > >  {
> > >  	u32 val;
> > >  
> > > -	dev_priv->cdclk_pll.ref = 19200;
> > > -	dev_priv->cdclk_pll.vco = 0;
> > > +	cdclk_state->ref = 19200;
> > > +	cdclk_state->vco = 0;
> > >  
> > >  	val = I915_READ(BXT_DE_PLL_ENABLE);
> > >  	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
> > > @@ -1005,20 +1058,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> > >  		return;
> > >  
> > >  	val = I915_READ(BXT_DE_PLL_CTL);
> > > -	dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
> > > -		dev_priv->cdclk_pll.ref;
> > > +	cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
> > >  }
> > >  
> > > -static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
> > > +static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
> > > +			  struct intel_cdclk_state *cdclk_state)
> > >  {
> > >  	u32 divider;
> > > -	int div, vco;
> > > +	int div;
> > >  
> > > -	bxt_de_pll_update(dev_priv);
> > > +	bxt_de_pll_update(dev_priv, cdclk_state);
> > >  
> > > -	vco = dev_priv->cdclk_pll.vco;
> > > -	if (vco == 0)
> > > -		return dev_priv->cdclk_pll.ref;
> > > +	cdclk_state->cdclk = cdclk_state->ref;
> > > +
> > > +	if (cdclk_state->vco == 0)
> > > +		return;
> > >  
> > >  	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
> > >  
> > > @@ -1038,10 +1092,10 @@ static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
> > >  		break;
> > >  	default:
> > >  		MISSING_CASE(divider);
> > > -		return dev_priv->cdclk_pll.ref;
> > > +		return;
> > >  	}
> > >  
> > > -	return DIV_ROUND_CLOSEST(vco, div);
> > > +	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
> > >  }
> > >  
> > >  static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> > > @@ -1054,12 +1108,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> > >  				    1))
> > >  		DRM_ERROR("timeout waiting for DE PLL unlock\n");
> > >  
> > > -	dev_priv->cdclk_pll.vco = 0;
> > > +	dev_priv->cdclk.hw.vco = 0;
> > >  }
> > >  
> > >  static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
> > >  {
> > > -	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
> > > +	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
> > >  	u32 val;
> > >  
> > >  	val = I915_READ(BXT_DE_PLL_CTL);
> > > @@ -1077,7 +1131,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
> > >  				    1))
> > >  		DRM_ERROR("timeout waiting for DE PLL lock\n");
> > >  
> > > -	dev_priv->cdclk_pll.vco = vco;
> > > +	dev_priv->cdclk.hw.vco = vco;
> > >  }
> > >  
> > >  static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> > > @@ -1105,7 +1159,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> > >  		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> > >  		break;
> > >  	default:
> > > -		WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
> > > +		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
> > >  		WARN_ON(vco != 0);
> > >  
> > >  		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> > > @@ -1124,11 +1178,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> > >  		return;
> > >  	}
> > >  
> > > -	if (dev_priv->cdclk_pll.vco != 0 &&
> > > -	    dev_priv->cdclk_pll.vco != vco)
> > > +	if (dev_priv->cdclk.hw.vco != 0 &&
> > > +	    dev_priv->cdclk.hw.vco != vco)
> > >  		bxt_de_pll_disable(dev_priv);
> > >  
> > > -	if (dev_priv->cdclk_pll.vco != vco)
> > > +	if (dev_priv->cdclk.hw.vco != vco)
> > >  		bxt_de_pll_enable(dev_priv, vco);
> > >  
> > >  	val = divider | skl_cdclk_decimal(cdclk);
> > > @@ -1165,8 +1219,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> > >  
> > >  	intel_update_cdclk(dev_priv);
> > >  
> > > -	if (dev_priv->cdclk_pll.vco == 0 ||
> > > -	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> > > +	if (dev_priv->cdclk.hw.vco == 0 ||
> > > +	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
> > >  		goto sanitize;
> > >  
> > >  	/* DPLL okay; verify the cdclock
> > > @@ -1184,12 +1238,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> > >  	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
> > >  
> > >  	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
> > > -		   skl_cdclk_decimal(dev_priv->cdclk_freq);
> > > +		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
> > >  	/*
> > >  	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
> > >  	 * enable otherwise.
> > >  	 */
> > > -	if (dev_priv->cdclk_freq >= 500000)
> > > +	if (dev_priv->cdclk.hw.cdclk >= 500000)
> > >  		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> > >  
> > >  	if (cdctl == expected)
> > > @@ -1200,10 +1254,10 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> > >  	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> > >  
> > >  	/* force cdclk programming */
> > > -	dev_priv->cdclk_freq = 0;
> > > +	dev_priv->cdclk.hw.cdclk = 0;
> > >  
> > >  	/* force full PLL disable + enable */
> > > -	dev_priv->cdclk_pll.vco = -1;
> > > +	dev_priv->cdclk.hw.vco = -1;
> > >  }
> > >  
> > >  void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> > > @@ -1212,7 +1266,8 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> > >  
> > >  	bxt_sanitize_cdclk(dev_priv);
> > >  
> > > -	if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
> > > +	if (dev_priv->cdclk.hw.cdclk != 0 &&
> > > +	    dev_priv->cdclk.hw.vco != 0)
> > >  		return;
> > >  
> > >  	/*
> > > @@ -1233,7 +1288,13 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> > >  
> > >  void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
> > >  {
> > > -	bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> > > +	bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
> > > +}
> > > +
> > > +bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
> > > +			       const struct intel_cdclk_state *b)
> > > +{
> > > +	return memcmp(a, b, sizeof(*a)) == 0;
> > >  }
> > >  
> > >  static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
> > > @@ -1533,7 +1594,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> > >  		dev_priv->max_cdclk_freq = 400000;
> > >  	} else {
> > >  		/* otherwise assume cdclk is fixed */
> > > -		dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
> > > +		dev_priv->max_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> > >  	}
> > >  
> > >  	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
> > > @@ -1547,15 +1608,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> > >  
> > >  void intel_update_cdclk(struct drm_i915_private *dev_priv)
> > >  {
> > > -	dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
> > > +	dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw);
> > >  
> > > -	if (INTEL_GEN(dev_priv) >= 9)
> > > -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
> > > -				 dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
> > > -				 dev_priv->cdclk_pll.ref);
> > > -	else
> > > -		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
> > > -				 dev_priv->cdclk_freq);
> > > +	DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
> > > +			 dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco,
> > > +			 dev_priv->cdclk.hw.ref);
> > >  
> > >  	/*
> > >  	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
> > > @@ -1565,7 +1622,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv)
> > >  	 */
> > >  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > >  		I915_WRITE(GMBUSFREQ_VLV,
> > > -			   DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
> > > +			   DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000));
> > >  }
> > >  
> > >  static int pch_rawclk(struct drm_i915_private *dev_priv)
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index 519e5d663c5f..6c38ab299506 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -136,7 +136,7 @@ struct intel_limit {
> > >  };
> > >  
> > >  /* returns HPLL frequency in kHz */
> > > -static int valleyview_get_vco(struct drm_i915_private *dev_priv)
> > > +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
> > >  {
> > >  	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
> > >  
> > > @@ -172,7 +172,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> > >  			   const char *name, u32 reg)
> > >  {
> > >  	if (dev_priv->hpll_freq == 0)
> > > -		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
> > > +		dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
> > >  
> > >  	return vlv_get_cck_clock(dev_priv, name, reg,
> > >  				 dev_priv->hpll_freq);
> > > @@ -12436,7 +12436,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
> > >  	 */
> > >  	if (dev_priv->display.modeset_calc_cdclk) {
> > >  		if (!intel_state->cdclk_pll_vco)
> > > -			intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco;
> > > +			intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco;
> > >  		if (!intel_state->cdclk_pll_vco)
> > >  			intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
> > >  
> > > @@ -12456,8 +12456,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
> > >  		}
> > >  
> > >  		/* All pipes must be switched off while we change the cdclk. */
> > > -		if (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
> > > -		    intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) {
> > > +		if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> > > +		    intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
> > >  			ret = intel_modeset_all_pipes(state);
> > >  			if (ret < 0)
> > >  				return ret;
> > > @@ -12874,8 +12874,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> > >  		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
> > >  
> > >  		if (dev_priv->display.modeset_commit_cdclk &&
> > > -		    (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
> > > -		     intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco))
> > > +		    (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> > > +		     intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
> > >  			dev_priv->display.modeset_commit_cdclk(state);
> > >  
> > >  		/*
> > > @@ -14724,7 +14724,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
> > >  
> > >  	intel_update_cdclk(dev_priv);
> > >  
> > > -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
> > > +	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> > >  
> > >  	intel_init_clock_gating(dev_priv);
> > >  }
> > > @@ -14897,7 +14897,7 @@ int intel_modeset_init(struct drm_device *dev)
> > >  
> > >  	intel_update_czclk(dev_priv);
> > >  	intel_update_cdclk(dev_priv);
> > > -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
> > > +	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> > >  
> > >  	intel_shared_dpll_init(dev);
> > >  
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 45ebc9632633..73a708b8d887 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -885,7 +885,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
> > >  	 * divide by 2000 and use that
> > >  	 */
> > >  	if (intel_dig_port->port == PORT_A)
> > > -		return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
> > > +		return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000);
> > >  	else
> > >  		return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
> > >  }
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index 8d93b7bda3ff..cc0122282a7b 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -1225,10 +1225,13 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
> > >  void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
> > >  void intel_update_cdclk(struct drm_i915_private *dev_priv);
> > >  void intel_update_rawclk(struct drm_i915_private *dev_priv);
> > > +bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
> > > +			       const struct intel_cdclk_state *b);
> > >  
> > >  /* intel_display.c */
> > >  enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
> > >  void intel_update_rawclk(struct drm_i915_private *dev_priv);
> > > +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
> > >  int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
> > >  		      const char *name, u32 reg, int ref_freq);
> > >  int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> > > index 463056d80f9b..385251e48c74 100644
> > > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > > @@ -829,7 +829,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
> > >  
> > >  	/* WaFbcExceedCdClockThreshold:hsw,bdw */
> > >  	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
> > > -	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) {
> > > +	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) {
> > >  		fbc->no_fbc_reason = "pixel rate is too big";
> > >  		return false;
> > >  	}
> > > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > > index 1a6ff26dea20..cb50c527401f 100644
> > > --- a/drivers/gpu/drm/i915/intel_panel.c
> > > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > > @@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> > >  	if (IS_PINEVIEW(dev_priv))
> > >  		clock = KHz(dev_priv->rawclk_freq);
> > >  	else
> > > -		clock = KHz(dev_priv->cdclk_freq);
> > > +		clock = KHz(dev_priv->cdclk.hw.cdclk);
> > >  
> > >  	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
> > >  }
> > > @@ -1333,7 +1333,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> > >  	if (IS_G4X(dev_priv))
> > >  		clock = KHz(dev_priv->rawclk_freq);
> > >  	else
> > > -		clock = KHz(dev_priv->cdclk_freq);
> > > +		clock = KHz(dev_priv->cdclk.hw.cdclk);
> > >  
> > >  	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
> > >  }
> > > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > index 6d5efeb35823..14bbecc8f2ed 100644
> > > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > @@ -964,9 +964,12 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
> > >  static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
> > >  					  struct i915_power_well *power_well)
> > >  {
> > > +	struct intel_cdclk_state cdclk_state = {};
> > > +
> > >  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
> > >  
> > > -	WARN_ON(dev_priv->cdclk_freq != dev_priv->display.get_cdclk(dev_priv));
> > > +	dev_priv->display.get_cdclk(dev_priv, &cdclk_state);
> > > +	WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state));
> > >  
> > >  	gen9_assert_dbuf_enabled(dev_priv);
> > >  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 08/14] drm/i915: Track full cdclk state for the logical and actual cdclk frequencies
  2016-12-19 17:28 ` [PATCH v2 08/14] drm/i915: Track full cdclk state for the logical and actual cdclk frequencies ville.syrjala
@ 2016-12-23 11:53   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 11:53 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The current dev_cdclk vs. cdclk vs. atomic_cdclk_freq is quite a mess.
> So here I'm introducing the "actual" and "logical" naming for our
> cdclk state. "actual" is what we'll bash into the hardware and "logical"
> is what everyone should use for state computaion/checking and whatnot.
> We'll track both using the intel_cdclk_state as both will need other
> differing parameters than just the actual cdclk frequency.
> 
> While doing that we can at the same time unify the appearance of the
> .modeset_calc_cdclk() implementations a little bit.
> 
> v2: Commit dev_priv->cdclk.actual since that already has the
>     new state by the time .modeset_commit_cdclk() is called.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  13 ++--
>  drivers/gpu/drm/i915/intel_cdclk.c   | 123 ++++++++++++++++++++++-------------
>  drivers/gpu/drm/i915/intel_display.c |  39 ++++++-----
>  drivers/gpu/drm/i915/intel_dp.c      |   2 +-
>  drivers/gpu/drm/i915/intel_drv.h     |  24 ++++---
>  drivers/gpu/drm/i915/intel_pm.c      |   4 +-
>  6 files changed, 121 insertions(+), 84 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index a4f1231ff8ca..b5a8d0f4cfbd 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2237,18 +2237,19 @@ struct drm_i915_private {
>  	unsigned int skl_preferred_vco_freq;
>  	unsigned int max_cdclk_freq;
>  
> -	/*
> -	 * For reading holding any crtc lock is sufficient,
> -	 * for writing must hold all of them.
> -	 */
> -	unsigned int atomic_cdclk_freq;
> -
>  	unsigned int max_dotclk_freq;
>  	unsigned int rawclk_freq;
>  	unsigned int hpll_freq;
>  	unsigned int czclk_freq;
>  
>  	struct {
> +		/*
> +		 * The current logical cdclk state.
> +		 * For reading holding any crtc lock is sufficient,
> +		 * for writing must hold all of them.
> +		 */
> +		struct intel_cdclk_state logical;
> +		struct intel_cdclk_state actual;
>  		struct intel_cdclk_state hw;

It would be great if all three fields were documented, including an example
configuration where the logical and actual fields differ and what which fields
hold, to make the distinction clear.

>  	} cdclk;
>  
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
> index 13c3b5555473..08ae3b78b8ed 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -1368,12 +1368,26 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
>  	int max_pixclk = intel_max_pixel_rate(state);
>  	struct intel_atomic_state *intel_state =
>  		to_intel_atomic_state(state);
> +	int cdclk;
> +
> +	cdclk = vlv_calc_cdclk(dev_priv, max_pixclk);
> +
> +	if (cdclk > dev_priv->max_cdclk_freq) {
> +		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
> +			      cdclk, dev_priv->max_cdclk_freq);
> +		return -EINVAL;
> +	}
>  
> -	intel_state->cdclk = intel_state->dev_cdclk =
> -		vlv_calc_cdclk(dev_priv, max_pixclk);
> +	intel_state->cdclk.logical.cdclk = cdclk;
>  
> -	if (!intel_state->active_crtcs)
> -		intel_state->dev_cdclk = vlv_calc_cdclk(dev_priv, 0);
> +	if (!intel_state->active_crtcs) {
> +		cdclk = vlv_calc_cdclk(dev_priv, 0);
> +
> +		intel_state->cdclk.actual.cdclk = cdclk;
> +	} else {
> +		intel_state->cdclk.actual =
> +			intel_state->cdclk.logical;
> +	}
>  
>  	return 0;
>  }
> @@ -1382,9 +1396,7 @@ static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_device *dev = old_state->dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct intel_atomic_state *old_intel_state =
> -		to_intel_atomic_state(old_state);
> -	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
>  
>  	/*
>  	 * FIXME: We can end up here with all power domains off, yet
> @@ -1426,9 +1438,16 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
>  		return -EINVAL;
>  	}
>  
> -	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> -	if (!intel_state->active_crtcs)
> -		intel_state->dev_cdclk = bdw_calc_cdclk(0);
> +	intel_state->cdclk.logical.cdclk = cdclk;
> +
> +	if (!intel_state->active_crtcs) {
> +		cdclk = bdw_calc_cdclk(0);
> +
> +		intel_state->cdclk.actual.cdclk = cdclk;
> +	} else {
> +		intel_state->cdclk.actual =
> +			intel_state->cdclk.logical;
> +	}
>  
>  	return 0;
>  }
> @@ -1436,9 +1455,7 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
>  static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_device *dev = old_state->dev;
> -	struct intel_atomic_state *old_intel_state =
> -		to_intel_atomic_state(old_state);
> -	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +	unsigned int req_cdclk = to_i915(dev)->cdclk.actual.cdclk;
>  
>  	bdw_set_cdclk(dev, req_cdclk);
>  }
> @@ -1448,8 +1465,11 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
>  	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
>  	struct drm_i915_private *dev_priv = to_i915(state->dev);
>  	const int max_pixclk = intel_max_pixel_rate(state);
> -	int vco = intel_state->cdclk_pll_vco;
> -	int cdclk;
> +	int cdclk, vco;
> +
> +	vco = intel_state->cdclk.logical.vco;
> +	if (!vco)
> +		vco = dev_priv->skl_preferred_vco_freq;
>  
>  	/*
>  	 * FIXME should also account for plane ratio
> @@ -1457,19 +1477,24 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
>  	 */
>  	cdclk = skl_calc_cdclk(max_pixclk, vco);
>  
> -	/*
> -	 * FIXME move the cdclk caclulation to
> -	 * compute_config() so we can fail gracegully.
> -	 */
>  	if (cdclk > dev_priv->max_cdclk_freq) {
> -		DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
> -			  cdclk, dev_priv->max_cdclk_freq);
> -		cdclk = dev_priv->max_cdclk_freq;
> +		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
> +			      cdclk, dev_priv->max_cdclk_freq);
> +		return -EINVAL;
>  	}
>  
> -	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> -	if (!intel_state->active_crtcs)
> -		intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
> +	intel_state->cdclk.logical.vco = vco;
> +	intel_state->cdclk.logical.cdclk = cdclk;
> +
> +	if (!intel_state->active_crtcs) {
> +		cdclk = skl_calc_cdclk(0, vco);
> +
> +		intel_state->cdclk.actual.vco = vco;
> +		intel_state->cdclk.actual.cdclk = cdclk;
> +	} else {
> +		intel_state->cdclk.actual =
> +			intel_state->cdclk.logical;
> +	}
>  
>  	return 0;
>  }
> @@ -1477,10 +1502,8 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
>  static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -	struct intel_atomic_state *intel_state =
> -		to_intel_atomic_state(old_state);
> -	unsigned int req_cdclk = intel_state->dev_cdclk;
> -	unsigned int req_vco = intel_state->cdclk_pll_vco;
> +	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
> +	unsigned int req_vco = dev_priv->cdclk.actual.vco;
>  
>  	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
>  }
> @@ -1491,22 +1514,39 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
>  	int max_pixclk = intel_max_pixel_rate(state);
>  	struct intel_atomic_state *intel_state =
>  		to_intel_atomic_state(state);
> -	int cdclk;
> +	int cdclk, vco;
>  
> -	if (IS_GEMINILAKE(dev_priv))
> +	if (IS_GEMINILAKE(dev_priv)) {
>  		cdclk = glk_calc_cdclk(max_pixclk);
> -	else
> +		vco = glk_de_pll_vco(dev_priv, cdclk);
> +	} else {
>  		cdclk = bxt_calc_cdclk(max_pixclk);
> +		vco = bxt_de_pll_vco(dev_priv, cdclk);
> +	}
> +
> +	if (cdclk > dev_priv->max_cdclk_freq) {
> +		DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
> +			      cdclk, dev_priv->max_cdclk_freq);
> +		return -EINVAL;
> +	}
>  
> -	intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> +	intel_state->cdclk.logical.vco = vco;
> +	intel_state->cdclk.logical.cdclk = cdclk;
>  
>  	if (!intel_state->active_crtcs) {
> -		if (IS_GEMINILAKE(dev_priv))
> +		if (IS_GEMINILAKE(dev_priv)) {
>  			cdclk = glk_calc_cdclk(0);
> -		else
> +			vco = glk_de_pll_vco(dev_priv, cdclk);
> +		} else {
>  			cdclk = bxt_calc_cdclk(0);
> +			vco = bxt_de_pll_vco(dev_priv, cdclk);
> +		}
>  
> -		intel_state->dev_cdclk = cdclk;
> +		intel_state->cdclk.actual.vco = vco;
> +		intel_state->cdclk.actual.cdclk = cdclk;
> +	} else {
> +		intel_state->cdclk.actual =
> +			intel_state->cdclk.logical;
>  	}
>  
>  	return 0;
> @@ -1515,15 +1555,8 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
>  static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -	struct intel_atomic_state *old_intel_state =
> -		to_intel_atomic_state(old_state);
> -	unsigned int req_cdclk = old_intel_state->dev_cdclk;
> -	unsigned int req_vco;
> -
> -	if (IS_GEMINILAKE(dev_priv))
> -		req_vco = glk_de_pll_vco(dev_priv, req_cdclk);
> -	else
> -		req_vco = bxt_de_pll_vco(dev_priv, req_cdclk);
> +	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
> +	unsigned int req_vco = dev_priv->cdclk.actual.vco;
>  
>  	bxt_set_cdclk(dev_priv, req_cdclk, req_vco);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 6c38ab299506..fb3abb58b6ca 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12416,6 +12416,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
>  
>  	intel_state->modeset = true;
>  	intel_state->active_crtcs = dev_priv->active_crtcs;
> +	intel_state->cdclk.logical = dev_priv->cdclk.logical;
> +	intel_state->cdclk.actual = dev_priv->cdclk.actual;

Not an issue with this patch specifically, but shouldn't this be part of a
duplicate_cdclk_state() to be inline with other atomic stuff?
>  
>  	for_each_crtc_in_state(state, crtc, crtc_state, i) {
>  		if (crtc_state->active)
> @@ -12435,38 +12437,35 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
>  	 * adjusted_mode bits in the crtc directly.
>  	 */
>  	if (dev_priv->display.modeset_calc_cdclk) {
> -		if (!intel_state->cdclk_pll_vco)
> -			intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco;
> -		if (!intel_state->cdclk_pll_vco)
> -			intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
> -
>  		ret = dev_priv->display.modeset_calc_cdclk(state);
>  		if (ret < 0)
>  			return ret;
>  
>  		/*
> -		 * Writes to dev_priv->atomic_cdclk_freq must protected by
> +		 * Writes to dev_priv->cdclk_locical must protected by

logical

>  		 * holding all the crtc locks, even if we don't end up
>  		 * touching the hardware
>  		 */
> -		if (intel_state->cdclk != dev_priv->atomic_cdclk_freq) {
> +		if (!intel_cdclk_state_compare(&dev_priv->cdclk.logical,
> +					       &intel_state->cdclk.logical)) {
>  			ret = intel_lock_all_pipes(state);
>  			if (ret < 0)
>  				return ret;
>  		}
>  
>  		/* All pipes must be switched off while we change the cdclk. */
> -		if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> -		    intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) {
> +		if (!intel_cdclk_state_compare(&dev_priv->cdclk.actual,
> +					       &intel_state->cdclk.actual)) {
>  			ret = intel_modeset_all_pipes(state);
>  			if (ret < 0)
>  				return ret;
>  		}
>  
> -		DRM_DEBUG_KMS("New cdclk calculated to be atomic %u, actual %u\n",
> -			      intel_state->cdclk, intel_state->dev_cdclk);
> +		DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n",
> +			      intel_state->cdclk.logical.cdclk,
> +			      intel_state->cdclk.actual.cdclk);
>  	} else {
> -		to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
> +		to_intel_atomic_state(state)->cdclk.logical = dev_priv->cdclk.logical;
>  	}
>  
>  	intel_modeset_clear_plls(state);
> @@ -12569,7 +12568,7 @@ static int intel_atomic_check(struct drm_device *dev,
>  		if (ret)
>  			return ret;
>  	} else {
> -		intel_state->cdclk = dev_priv->atomic_cdclk_freq;
> +		intel_state->cdclk.logical = dev_priv->cdclk.logical;
>  	}
>  
>  	ret = drm_atomic_helper_check_planes(dev, state);
> @@ -12874,8 +12873,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>  		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
>  
>  		if (dev_priv->display.modeset_commit_cdclk &&
> -		    (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk ||
> -		     intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco))
> +		    !intel_cdclk_state_compare(&dev_priv->cdclk.hw,
> +					       &dev_priv->cdclk.actual))
>  			dev_priv->display.modeset_commit_cdclk(state);
>  
>  		/*
> @@ -13056,7 +13055,8 @@ static int intel_atomic_commit(struct drm_device *dev,
>  		memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
>  		       sizeof(intel_state->min_pixclk));
>  		dev_priv->active_crtcs = intel_state->active_crtcs;
> -		dev_priv->atomic_cdclk_freq = intel_state->cdclk;
> +		dev_priv->cdclk.logical = intel_state->cdclk.logical;
> +		dev_priv->cdclk.actual = intel_state->cdclk.actual;
>  	}
>  
>  	drm_atomic_state_get(state);
> @@ -13298,7 +13298,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
>  		return DRM_PLANE_HELPER_NO_SCALING;
>  
>  	crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
> -	cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
> +	cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk;
>  
>  	if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock))
>  		return DRM_PLANE_HELPER_NO_SCALING;
> @@ -14723,8 +14723,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  
>  	intel_update_cdclk(dev_priv);
> -
> -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> +	dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw;
>  
>  	intel_init_clock_gating(dev_priv);
>  }
> @@ -14897,7 +14896,7 @@ int intel_modeset_init(struct drm_device *dev)
>  
>  	intel_update_czclk(dev_priv);
>  	intel_update_cdclk(dev_priv);
> -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk;
> +	dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw;
>  
>  	intel_shared_dpll_init(dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 73a708b8d887..4309509e8a34 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1734,7 +1734,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>  			break;
>  		}
>  
> -		to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco;
> +		to_intel_atomic_state(pipe_config->base.state)->cdclk.logical.vco = vco;
>  	}
>  
>  	if (!HAS_DDI(dev_priv))
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index cc0122282a7b..d167ee458d63 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -333,13 +333,20 @@ struct dpll {
>  struct intel_atomic_state {
>  	struct drm_atomic_state base;
>  
> -	unsigned int cdclk;
> -
> -	/*
> -	 * Calculated device cdclk, can be different from cdclk
> -	 * only when all crtc's are DPMS off.
> -	 */
> -	unsigned int dev_cdclk;
> +	struct {
> +		/*
> +		 * Logical state of cdclk (used for all scaling, watermark,
> +		 * etc. calculations and checks). This is computed as if all
> +		 * enabled crtcs were active.
> +		 */
> +		struct intel_cdclk_state logical;
> +
> +		/*
> +		 * Actual state of cdclk, can be different from the logical
> +		 * state only when all crtc's are DPMS off.
> +		 */
> +		struct intel_cdclk_state actual;
> +	} cdclk;

Ah, here's the field descriptions. Maybe the fields in dev_priv should point at
here. Compared to the other atomic states, the cdclk one is a bit different,
since there's only once cdclk per device but we have multiple states. Maybe the
state struct should have both logical and actual, and dev_priv would include
only one struct intel_cdclk_state? Then there would be only one place for
documentation and it would be more inline with other atomic stuff.

I agree that the patch does make things less confusing, though, so 

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

>  
>  	bool dpll_set, modeset;
>  
> @@ -356,9 +363,6 @@ struct intel_atomic_state {
>  	unsigned int active_crtcs;
>  	unsigned int min_pixclk[I915_MAX_PIPES];
>  
> -	/* SKL/KBL Only */
> -	unsigned int cdclk_pll_vco;
> -
>  	struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
>  
>  	/*
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 79e2be4216e4..fe522ec21502 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2095,7 +2095,7 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *cstate)
>  		return 0;
>  	if (WARN_ON(adjusted_mode->crtc_clock == 0))
>  		return 0;
> -	if (WARN_ON(intel_state->cdclk == 0))
> +	if (WARN_ON(intel_state->cdclk.logical.cdclk == 0))
>  		return 0;
>  
>  	/* The WM are computed with base on how long it takes to fill a single
> @@ -2104,7 +2104,7 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *cstate)
>  	linetime = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8,
>  				     adjusted_mode->crtc_clock);
>  	ips_linetime = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8,
> -					 intel_state->cdclk);
> +					 intel_state->cdclk.logical.cdclk);
>  
>  	return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
>  	       PIPE_WM_LINETIME_TIME(linetime);
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 09/14] drm/i915: Pass dev_priv to remainder of the cdclk functions
  2016-12-19 17:28 ` [PATCH v2 09/14] drm/i915: Pass dev_priv to remainder of the cdclk functions ville.syrjala
@ 2016-12-23 12:01   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 12:01 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Clean up the dev vs. dev_priv straggles that are making things
> look inconsistentt.
> 
> v2: Deal with churn
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> ---
>  drivers/gpu/drm/i915/intel_cdclk.c | 25 ++++++++++---------------
>  1 file changed, 10 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> b/drivers/gpu/drm/i915/intel_cdclk.c
> index 08ae3b78b8ed..2e998fa087a9 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -433,9 +433,8 @@ static void vlv_program_pfi_credits(struct
> drm_i915_private *dev_priv)
>  	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
>  }
>  
> -static void vlv_set_cdclk(struct drm_device *dev, int cdclk)
> +static void vlv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(dev);
>  	u32 val, cmd;
>  
>  	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
> @@ -496,9 +495,8 @@ static void vlv_set_cdclk(struct drm_device *dev, int
> cdclk)
>  	intel_update_cdclk(dev_priv);
>  }
>  
> -static void chv_set_cdclk(struct drm_device *dev, int cdclk)
> +static void chv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(dev);
>  	u32 val, cmd;
>  
>  	switch (cdclk) {
> @@ -566,9 +564,8 @@ static void bdw_get_cdclk(struct drm_i915_private
> *dev_priv,
>  		cdclk_state->cdclk = 675000;
>  }
>  
> -static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
> +static void bdw_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(dev);
>  	uint32_t val, data;
>  	int ret;
>  
> @@ -1363,8 +1360,7 @@ static int intel_max_pixel_rate(struct drm_atomic_state
> *state)
>  
>  static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
>  {
> -	struct drm_device *dev = state->dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct drm_i915_private *dev_priv = to_i915(state->dev);
>  	int max_pixclk = intel_max_pixel_rate(state);
>  	struct intel_atomic_state *intel_state =
>  		to_intel_atomic_state(state);
> @@ -1394,8 +1390,7 @@ static int vlv_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  
>  static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
> -	struct drm_device *dev = old_state->dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
>  	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
>  
>  	/*
> @@ -1410,9 +1405,9 @@ static void vlv_modeset_commit_cdclk(struct
> drm_atomic_state *old_state)
>  	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
>  
>  	if (IS_CHERRYVIEW(dev_priv))
> -		chv_set_cdclk(dev, req_cdclk);
> +		chv_set_cdclk(dev_priv, req_cdclk);
>  	else
> -		vlv_set_cdclk(dev, req_cdclk);
> +		vlv_set_cdclk(dev_priv, req_cdclk);
>  
>  	vlv_program_pfi_credits(dev_priv);
>  
> @@ -1454,10 +1449,10 @@ static int bdw_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  
>  static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
> -	struct drm_device *dev = old_state->dev;
> -	unsigned int req_cdclk = to_i915(dev)->cdclk.actual.cdclk;
> +	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> +	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
>  
> -	bdw_set_cdclk(dev, req_cdclk);
> +	bdw_set_cdclk(dev_priv, req_cdclk);
>  }
>  
>  static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure
  2016-12-23  9:09       ` Ander Conselvan De Oliveira
@ 2016-12-23 12:27         ` Ville Syrjälä
  2016-12-23 13:07           ` Ander Conselvan De Oliveira
  0 siblings, 1 reply; 40+ messages in thread
From: Ville Syrjälä @ 2016-12-23 12:27 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira; +Cc: intel-gfx, Rodrigo Vivi

On Fri, Dec 23, 2016 at 11:09:22AM +0200, Ander Conselvan De Oliveira wrote:
> On Thu, 2016-12-22 at 16:33 +0200, Ville Syrjälä wrote:
> > On Thu, Dec 22, 2016 at 04:14:40PM +0200, Ander Conselvan De Oliveira wrote:
> > > 
> > > On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > > > 
> > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > 
> > > > Introduce intel_cdclk state which for now will track the cdclk
> > > > frequency, the vco frequency and the reference frequency (not sure we
> > > > want the last one, but I put it there anyway). We'll also make the
> > > > .get_cdclk() function fill out this state structure rather than
> > > > just returning the current cdclk frequency.
> > > > 
> > > > One immediate benefit is that calling .get_cdclk() will no longer
> > > > clobber state stored under dev_priv unless ex[plicitly told to do
> > > Typo: ex[plicity
> > > 
> > > > 
> > > > so. Previously it clobbered the vco and reference clocks stored
> > > > there on some platforms.
> > > > 
> > > > We'll expand the use of this structure to actually precomputing the
> > > > state and whatnot later.
> > > > 
> > > > v2: Constify intel_cdclk_state_compare()
> > > > 
> > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > A couple more comments beloew, but either way,
> > > 
> > > Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
> > > 
> > > > 
> > > > ---
> > > >  drivers/gpu/drm/i915/i915_debugfs.c     |   2 +-
> > > >  drivers/gpu/drm/i915/i915_drv.h         |  14 +-
> > > >  drivers/gpu/drm/i915/intel_audio.c      |   2 +-
> > > >  drivers/gpu/drm/i915/intel_cdclk.c      | 359 ++++++++++++++++++--------------
> > > >  drivers/gpu/drm/i915/intel_display.c    |  18 +-
> > > >  drivers/gpu/drm/i915/intel_dp.c         |   2 +-
> > > >  drivers/gpu/drm/i915/intel_drv.h        |   3 +
> > > >  drivers/gpu/drm/i915/intel_fbc.c        |   2 +-
> > > >  drivers/gpu/drm/i915/intel_panel.c      |   4 +-
> > > >  drivers/gpu/drm/i915/intel_runtime_pm.c |   5 +-
> > > >  10 files changed, 240 insertions(+), 171 deletions(-)
> > > > 
> 
> [...]
> 
> @@ -629,12 +668,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco)
> > > >  }
> > > >  
> > > > -static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> > > > +static void skl_dpll0_update(struct drm_i915_private *dev_priv,
> > > > +			     struct intel_cdclk_state *cdclk_state)
> > > >  {
> > > >  	u32 val;
> > > >  
> > > > -	dev_priv->cdclk_pll.ref = 24000;
> > > > -	dev_priv->cdclk_pll.vco = 0;
> > > > +	cdclk_state->ref = 24000;
> > > > +	cdclk_state->vco = 0;
> > > >  
> > > >  	val = I915_READ(LCPLL1_CTL);
> > > >  	if ((val & LCPLL_PLL_ENABLE) == 0)
> > > > @@ -656,11 +696,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
> > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
> > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
> > > > -		dev_priv->cdclk_pll.vco = 8100000;
> > > > +		cdclk_state->vco = 8100000;
> > > >  		break;
> > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
> > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
> > > > -		dev_priv->cdclk_pll.vco = 8640000;
> > > > +		cdclk_state->vco = 8640000;
> > > >  		break;
> > > >  	default:
> > > >  		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> > > This function is a bit funny now, since it sets up the cdclk state based on
> > > current pll0 programming, instead of looking at an atomic state.
> > We should probably rename it to somehting more descriptive. skl_get_dpll0()
> > maybe. Or maybe skl_dpll0_get_config to match the .get_config()
> > nomenclature used for eg. encoders.
> 
> Hmm, I think the problem is that this have a mix of get_hw_state() and
> get_config(). We actually have skl_ddi_dpll0_get_hw_state(), but it wouldn't be
> trivial to make that code reusable for the cdclk stuff.
> 
> Maybe it should be two separate functions, one that gets the hardware state and
> another for choosing the vco.

This function only exists to read the hw state.

> Then
> 
>   vco = skl_cdclk_vco(skl_dpll0_get_hw_state());
> 
> directly in skl_get_cdclk() ? I'm not really sure, maybe just leave the way it
> is for now.
> 
> >  Though if we go there then
> > .get_cdclk() might need to be renamed to .cdclk_get_config or something.
> 
> .cdclk_get_hw_state() ?

.get_hw_state() is the thing which tells us if something is enabled,
.get_config() is the thing that actually reads out the full state. Or at
least that's how it used to be.

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

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

* Re: [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure
  2016-12-23 12:27         ` Ville Syrjälä
@ 2016-12-23 13:07           ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 13:07 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Rodrigo Vivi

On Fri, 2016-12-23 at 14:27 +0200, Ville Syrjälä wrote:
> On Fri, Dec 23, 2016 at 11:09:22AM +0200, Ander Conselvan De Oliveira wrote:
> > 
> > On Thu, 2016-12-22 at 16:33 +0200, Ville Syrjälä wrote:
> > > 
> > > On Thu, Dec 22, 2016 at 04:14:40PM +0200, Ander Conselvan De Oliveira
> > > wrote:
> > > > 
> > > > 
> > > > On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > > > > 
> > > > > 
> > > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > 
> > > > > Introduce intel_cdclk state which for now will track the cdclk
> > > > > frequency, the vco frequency and the reference frequency (not sure we
> > > > > want the last one, but I put it there anyway). We'll also make the
> > > > > .get_cdclk() function fill out this state structure rather than
> > > > > just returning the current cdclk frequency.
> > > > > 
> > > > > One immediate benefit is that calling .get_cdclk() will no longer
> > > > > clobber state stored under dev_priv unless ex[plicitly told to do
> > > > Typo: ex[plicity
> > > > 
> > > > > 
> > > > > 
> > > > > so. Previously it clobbered the vco and reference clocks stored
> > > > > there on some platforms.
> > > > > 
> > > > > We'll expand the use of this structure to actually precomputing the
> > > > > state and whatnot later.
> > > > > 
> > > > > v2: Constify intel_cdclk_state_compare()
> > > > > 
> > > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > A couple more comments beloew, but either way,
> > > > 
> > > > Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
> > > > 
> > > > > 
> > > > > 
> > > > > ---
> > > > >  drivers/gpu/drm/i915/i915_debugfs.c     |   2 +-
> > > > >  drivers/gpu/drm/i915/i915_drv.h         |  14 +-
> > > > >  drivers/gpu/drm/i915/intel_audio.c      |   2 +-
> > > > >  drivers/gpu/drm/i915/intel_cdclk.c      | 359 ++++++++++++++++++-----
> > > > > ---------
> > > > >  drivers/gpu/drm/i915/intel_display.c    |  18 +-
> > > > >  drivers/gpu/drm/i915/intel_dp.c         |   2 +-
> > > > >  drivers/gpu/drm/i915/intel_drv.h        |   3 +
> > > > >  drivers/gpu/drm/i915/intel_fbc.c        |   2 +-
> > > > >  drivers/gpu/drm/i915/intel_panel.c      |   4 +-
> > > > >  drivers/gpu/drm/i915/intel_runtime_pm.c |   5 +-
> > > > >  10 files changed, 240 insertions(+), 171 deletions(-)
> > > > > 
> > [...]
> > 
> > @@ -629,12 +668,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco)
> > > 
> > > > 
> > > > > 
> > > > >  }
> > > > >  
> > > > > -static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> > > > > +static void skl_dpll0_update(struct drm_i915_private *dev_priv,
> > > > > +			     struct intel_cdclk_state *cdclk_state)
> > > > >  {
> > > > >  	u32 val;
> > > > >  
> > > > > -	dev_priv->cdclk_pll.ref = 24000;
> > > > > -	dev_priv->cdclk_pll.vco = 0;
> > > > > +	cdclk_state->ref = 24000;
> > > > > +	cdclk_state->vco = 0;
> > > > >  
> > > > >  	val = I915_READ(LCPLL1_CTL);
> > > > >  	if ((val & LCPLL_PLL_ENABLE) == 0)
> > > > > @@ -656,11 +696,11 @@ static void skl_dpll0_update(struct
> > > > > drm_i915_private *dev_priv)
> > > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350,
> > > > > SKL_DPLL0):
> > > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620,
> > > > > SKL_DPLL0):
> > > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700,
> > > > > SKL_DPLL0):
> > > > > -		dev_priv->cdclk_pll.vco = 8100000;
> > > > > +		cdclk_state->vco = 8100000;
> > > > >  		break;
> > > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
> > > > > SKL_DPLL0):
> > > > >  	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160,
> > > > > SKL_DPLL0):
> > > > > -		dev_priv->cdclk_pll.vco = 8640000;
> > > > > +		cdclk_state->vco = 8640000;
> > > > >  		break;
> > > > >  	default:
> > > > >  		MISSING_CASE(val &
> > > > > DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> > > > This function is a bit funny now, since it sets up the cdclk state based
> > > > on
> > > > current pll0 programming, instead of looking at an atomic state.
> > > We should probably rename it to somehting more descriptive.
> > > skl_get_dpll0()
> > > maybe. Or maybe skl_dpll0_get_config to match the .get_config()
> > > nomenclature used for eg. encoders.
> > Hmm, I think the problem is that this have a mix of get_hw_state() and
> > get_config(). We actually have skl_ddi_dpll0_get_hw_state(), but it wouldn't
> > be
> > trivial to make that code reusable for the cdclk stuff.
> > 
> > Maybe it should be two separate functions, one that gets the hardware state
> > and
> > another for choosing the vco.
> This function only exists to read the hw state.

Then get_hw_state() wouldn't be a bad name. The only difference between this and
the pll get_hw_state() hook is that the latter doesn't set a vco value, since
that is not directly programmed.

> 
> > 
> > Then
> > 
> >   vco = skl_cdclk_vco(skl_dpll0_get_hw_state());
> > 
> > directly in skl_get_cdclk() ? I'm not really sure, maybe just leave the way
> > it
> > is for now.
> > 
> > > 
> > >  Though if we go there then
> > > .get_cdclk() might need to be renamed to .cdclk_get_config or something.
> > .cdclk_get_hw_state() ?
> .get_hw_state() is the thing which tells us if something is enabled,
> .get_config() is the thing that actually reads out the full state. Or at
> least that's how it used to be.

For encoders, get_hw_state() may also read what pipe it is in. For crtcs,
get_pipe_config() does both. PLLs get_hw_state() read the whole config too. I
guess there's room for making these more consistent. I'd go for is_enabled() for
something that is only supposed to say if something is enabled. :)

Ander



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

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

* Re: [PATCH v2 10/14] drm/i915: Pass the cdclk state to the set_cdclk() functions
  2016-12-19 17:28 ` [PATCH v2 10/14] drm/i915: Pass the cdclk state to the set_cdclk() functions ville.syrjala
@ 2016-12-23 13:43   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 13:43 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Rather than passing all the different parameters (cdclk,vco so
> far) sparately to the set_cdclk() functions, just pass the
> entire cdclk state.
> 
> v2: Deal with churn
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_cdclk.c | 79 +++++++++++++++++++++++---------------
>  1 file changed, 49 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
> index 2e998fa087a9..11a0f3e122c3 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -433,8 +433,10 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
>  	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
>  }
>  
> -static void vlv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> +static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
> +			  const struct intel_cdclk_state *cdclk_state)
>  {
> +	int cdclk = cdclk_state->cdclk;
>  	u32 val, cmd;
>  
>  	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
> @@ -495,8 +497,10 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
>  	intel_update_cdclk(dev_priv);
>  }
>  
> -static void chv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> +static void chv_set_cdclk(struct drm_i915_private *dev_priv,
> +			  const struct intel_cdclk_state *cdclk_state)
>  {
> +	int cdclk = cdclk_state->cdclk;
>  	u32 val, cmd;
>  
>  	switch (cdclk) {
> @@ -564,8 +568,10 @@ static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
>  		cdclk_state->cdclk = 675000;
>  }
>  
> -static void bdw_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> +static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
> +			  const struct intel_cdclk_state *cdclk_state)
>  {
> +	int cdclk = cdclk_state->cdclk;
>  	uint32_t val, data;
>  	int ret;
>  
> @@ -836,8 +842,10 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
>  }
>  
>  static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> -			  int cdclk, int vco)
> +			  const struct intel_cdclk_state *cdclk_state)
>  {
> +	int cdclk = cdclk_state->cdclk;
> +	int vco = cdclk_state->vco;
>  	u32 freq_select, pcu_ack;
>  	int ret;
>  
> @@ -942,12 +950,17 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  
>  void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
> +	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
> +
> +	cdclk_state.cdclk = cdclk_state.ref;
> +	cdclk_state.vco = 0;
> +
> +	skl_set_cdclk(dev_priv, &cdclk_state);
>  }
>  
>  void skl_init_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	int cdclk, vco;
> +	struct intel_cdclk_state cdclk_state;
>  
>  	skl_sanitize_cdclk(dev_priv);
>  
> @@ -963,12 +976,14 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
>  		return;
>  	}
>  
> -	vco = dev_priv->skl_preferred_vco_freq;
> -	if (vco == 0)
> -		vco = 8100000;
> -	cdclk = skl_calc_cdclk(0, vco);
> +	cdclk_state = dev_priv->cdclk.hw;

We need this assignments to preserve cdclk.ref?

> +
> +	cdclk_state.vco = dev_priv->skl_preferred_vco_freq;
> +	if (cdclk_state.vco == 0)
> +		cdclk_state.vco = 8100000;
> +	cdclk_state.cdclk = skl_calc_cdclk(0, cdclk_state.vco);
>  
> -	skl_set_cdclk(dev_priv, cdclk, vco);
> +	skl_set_cdclk(dev_priv, &cdclk_state);
>  }
>  
>  static int bxt_calc_cdclk(int max_pixclk)
> @@ -1132,8 +1147,10 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
>  }
>  
>  static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> -			  int cdclk, int vco)
> +			  const struct intel_cdclk_state *cdclk_state)
>  {
> +	int cdclk = cdclk_state->cdclk;
> +	int vco = cdclk_state->vco;
>  	u32 val, divider;
>  	int ret;
>  
> @@ -1259,7 +1276,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  
>  void bxt_init_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	int cdclk, vco;
> +	struct intel_cdclk_state cdclk_state;
>  
>  	bxt_sanitize_cdclk(dev_priv);
>  
> @@ -1267,25 +1284,33 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv)
>  	    dev_priv->cdclk.hw.vco != 0)
>  		return;
>  
> +	cdclk_state = dev_priv->cdclk.hw;
> +
>  	/*
>  	 * FIXME:
>  	 * - The initial CDCLK needs to be read from VBT.
>  	 *   Need to make this change after VBT has changes for BXT.
>  	 */
>  	if (IS_GEMINILAKE(dev_priv)) {
> -		cdclk = glk_calc_cdclk(0);
> -		vco = glk_de_pll_vco(dev_priv, cdclk);
> +		cdclk_state.cdclk = glk_calc_cdclk(0);
> +		cdclk_state.vco = glk_de_pll_vco(dev_priv, cdclk_state.cdclk);
>  	} else {
> -		cdclk = bxt_calc_cdclk(0);
> -		vco = bxt_de_pll_vco(dev_priv, cdclk);
> +		cdclk_state.ref = dev_priv->cdclk.hw.ref;

hw.ref was copied above already, no need to do it here. With that fixed,

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>


> +		cdclk_state.cdclk = bxt_calc_cdclk(0);
> +		cdclk_state.vco = bxt_de_pll_vco(dev_priv, cdclk_state.cdclk);
>  	}
>  
> -	bxt_set_cdclk(dev_priv, cdclk, vco);
> +	bxt_set_cdclk(dev_priv, &cdclk_state);
>  }
>  
>  void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
>  {
> -	bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0);
> +	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
> +
> +	cdclk_state.cdclk = cdclk_state.ref;
> +	cdclk_state.vco = 0;
> +
> +	bxt_set_cdclk(dev_priv, &cdclk_state);
>  }
>  
>  bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
> @@ -1391,7 +1416,6 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
>  static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
>  
>  	/*
>  	 * FIXME: We can end up here with all power domains off, yet
> @@ -1405,9 +1429,9 @@ static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
>  
>  	if (IS_CHERRYVIEW(dev_priv))
> -		chv_set_cdclk(dev_priv, req_cdclk);
> +		chv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  	else
> -		vlv_set_cdclk(dev_priv, req_cdclk);
> +		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  
>  	vlv_program_pfi_credits(dev_priv);
>  
> @@ -1450,9 +1474,8 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
>  static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
>  
> -	bdw_set_cdclk(dev_priv, req_cdclk);
> +	bdw_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  }
>  
>  static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
> @@ -1497,10 +1520,8 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
>  static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
> -	unsigned int req_vco = dev_priv->cdclk.actual.vco;
>  
> -	skl_set_cdclk(dev_priv, req_cdclk, req_vco);
> +	skl_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  }
>  
>  static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
> @@ -1550,10 +1571,8 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
>  static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -	unsigned int req_cdclk = dev_priv->cdclk.actual.cdclk;
> -	unsigned int req_vco = dev_priv->cdclk.actual.vco;
>  
> -	bxt_set_cdclk(dev_priv, req_cdclk, req_vco);
> +	bxt_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  }
>  
>  static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 11/14] drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk()
  2016-12-19 17:28 ` [PATCH 11/14] drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk() ville.syrjala
@ 2016-12-23 13:49   ` Ander Conselvan De Oliveira
  2016-12-23 14:07     ` Ville Syrjälä
  0 siblings, 1 reply; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 13:49 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Move the vlv_program_pfi_credits() into vlv_set_cdclk() and
> chv_set_cdclk() so that we can neuter vlv_modeset_commit_cdclk().
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_cdclk.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> b/drivers/gpu/drm/i915/intel_cdclk.c
> index 11a0f3e122c3..fe7a9e3a4f29 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -494,6 +494,8 @@ static void vlv_set_cdclk(struct drm_i915_private
> *dev_priv,
>  
>  	mutex_unlock(&dev_priv->sb_lock);
>  
> +	vlv_program_pfi_credits(dev_priv);
> +
>  	intel_update_cdclk(dev_priv);
>  }
>  
> @@ -533,6 +535,8 @@ static void chv_set_cdclk(struct drm_i915_private
> *dev_priv,
>  	}
>  	mutex_unlock(&dev_priv->rps.hw_lock);
>  
> +	vlv_program_pfi_credits(dev_priv);
> +
>  	intel_update_cdclk(dev_priv);

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

Can the vlv/chv register write in intel_update_cdclk() be moved to the set_cdclk() funcs too?


>  }
>  
> @@ -1433,7 +1437,6 @@ static void vlv_modeset_commit_cdclk(struct
> drm_atomic_state *old_state)
>  	else
>  		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  
> -	vlv_program_pfi_credits(dev_priv);
>  
>  	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
>  }



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

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

* Re: [PATCH 12/14] drm/i915: Nuke the VLV/CHV PFI programming power domain workaround
  2016-12-19 17:28 ` [PATCH 12/14] drm/i915: Nuke the VLV/CHV PFI programming power domain workaround ville.syrjala
@ 2016-12-23 13:52   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 13:52 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The hack to grab the pipe A power domain around VLV/CHV cdclk
> programming has surely outlived its usefulness. We should be
> hold sufficient power domains during any modeset, so let's just

hold/be holding?

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> nuke this hack.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_cdclk.c | 14 --------------
>  1 file changed, 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> b/drivers/gpu/drm/i915/intel_cdclk.c
> index fe7a9e3a4f29..bba077c4bd56 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -1421,24 +1421,10 @@ static void vlv_modeset_commit_cdclk(struct
> drm_atomic_state *old_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
>  
> -	/*
> -	 * FIXME: We can end up here with all power domains off, yet
> -	 * with a CDCLK frequency other than the minimum. To account
> -	 * for this take the PIPE-A power domain, which covers the HW
> -	 * blocks needed for the following programming. This can be
> -	 * removed once it's guaranteed that we get here either with
> -	 * the minimum CDCLK set, or the required power domains
> -	 * enabled.
> -	 */
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> -
>  	if (IS_CHERRYVIEW(dev_priv))
>  		chv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  	else
>  		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
> -
> -
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
>  }
>  
>  static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 13/14] drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct .set_cdclk() hook
  2016-12-19 17:28 ` [PATCH v2 13/14] drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct .set_cdclk() hook ville.syrjala
@ 2016-12-23 14:03   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 14:03 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> With the cdclk state, all the .modeset_commit_cdclk() hooks are
> now pointless wrappers. Let's replace them with just a .set_cdclk()
> function pointer. However let's wrap that in a small helper that
> does the state comparison and prints a unified debug message across
> all platforms. We didn't even have the debug print on all platforms
> previously. This reduces the clutter in intel_atomic_commit_tail() a
> little bit.
> 
> v2: Wrap .set_cdclk() in intel_set_cdclk()
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Nice cleanup!

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  3 +-
>  drivers/gpu/drm/i915/intel_cdclk.c   | 71 +++++++++++++--------------------
> ---
>  drivers/gpu/drm/i915/intel_display.c |  5 +--
>  drivers/gpu/drm/i915/intel_drv.h     |  2 +
>  4 files changed, 30 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index b5a8d0f4cfbd..faf753570a9a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -614,6 +614,8 @@ struct intel_cdclk_state;
>  struct drm_i915_display_funcs {
>  	void (*get_cdclk)(struct drm_i915_private *dev_priv,
>  			  struct intel_cdclk_state *cdclk_state);
> +	void (*set_cdclk)(struct drm_i915_private *dev_priv,
> +			  const struct intel_cdclk_state *cdclk_state);
>  	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
>  	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
>  	int (*compute_intermediate_wm)(struct drm_device *dev,
> @@ -628,7 +630,6 @@ struct drm_i915_display_funcs {
>  	int (*compute_global_watermarks)(struct drm_atomic_state *state);
>  	void (*update_wm)(struct intel_crtc *crtc);
>  	int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
> -	void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
>  	/* Returns the active state of the crtc, and if the crtc is active,
>  	 * fills out the pipe-config with the hw state. */
>  	bool (*get_pipe_config)(struct intel_crtc *,
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> b/drivers/gpu/drm/i915/intel_cdclk.c
> index bba077c4bd56..c2d995169528 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -855,9 +855,6 @@ static void skl_set_cdclk(struct drm_i915_private
> *dev_priv,
>  
>  	WARN_ON((cdclk == 24000) != (vco == 0));
>  
> -	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
> -			 cdclk, vco);
> -
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
>  				SKL_CDCLK_PREPARE_FOR_CHANGE,
> @@ -1158,9 +1155,6 @@ static void bxt_set_cdclk(struct drm_i915_private
> *dev_priv,
>  	u32 val, divider;
>  	int ret;
>  
> -	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
> -			 cdclk, vco);
> -
>  	/* cdclk = vco / 2 / div{1,1.5,2,4} */
>  	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
>  	case 8:
> @@ -1323,6 +1317,22 @@ bool intel_cdclk_state_compare(const struct
> intel_cdclk_state *a,
>  	return memcmp(a, b, sizeof(*a)) == 0;
>  }
>  
> +void intel_set_cdclk(struct drm_i915_private *dev_priv,
> +		     const struct intel_cdclk_state *cdclk_state)
> +{
> +	if (intel_cdclk_state_compare(&dev_priv->cdclk.hw, cdclk_state))
> +		return;
> +
> +	if (WARN_ON_ONCE(!dev_priv->display.set_cdclk))
> +		return;
> +
> +	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz, VCO %d kHz, ref %d
> kHz\n",
> +			 cdclk_state->cdclk, cdclk_state->vco,
> +			 cdclk_state->ref);
> +
> +	dev_priv->display.set_cdclk(dev_priv, cdclk_state);
> +}
> +
>  static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state
> *crtc_state,
>  					  int pixel_rate)
>  {
> @@ -1417,16 +1427,6 @@ static int vlv_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  	return 0;
>  }
>  
> -static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -
> -	if (IS_CHERRYVIEW(dev_priv))
> -		chv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
> -	else
> -		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
> -}
> -
>  static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->dev);
> @@ -1460,13 +1460,6 @@ static int bdw_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  	return 0;
>  }
>  
> -static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -
> -	bdw_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
> -}
> -
>  static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
>  {
>  	struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> @@ -1506,13 +1499,6 @@ static int skl_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  	return 0;
>  }
>  
> -static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -
> -	skl_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
> -}
> -
>  static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->dev);
> @@ -1557,13 +1543,6 @@ static int bxt_modeset_calc_cdclk(struct
> drm_atomic_state *state)
>  	return 0;
>  }
>  
> -static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> -
> -	bxt_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
> -}
> -
>  static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
>  {
>  	int max_cdclk_freq = dev_priv->max_cdclk_freq;
> @@ -1718,24 +1697,24 @@ void intel_update_rawclk(struct drm_i915_private
> *dev_priv)
>  
>  void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
>  {
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			vlv_modeset_commit_cdclk;
> +	if (IS_CHERRYVIEW(dev_priv)) {
> +		dev_priv->display.set_cdclk = chv_set_cdclk;
> +		dev_priv->display.modeset_calc_cdclk =
> +			vlv_modeset_calc_cdclk;
> +	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +		dev_priv->display.set_cdclk = vlv_set_cdclk;
>  		dev_priv->display.modeset_calc_cdclk =
>  			vlv_modeset_calc_cdclk;
>  	} else if (IS_BROADWELL(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			bdw_modeset_commit_cdclk;
> +		dev_priv->display.set_cdclk = bdw_set_cdclk;
>  		dev_priv->display.modeset_calc_cdclk =
>  			bdw_modeset_calc_cdclk;
>  	} else if (IS_GEN9_LP(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			bxt_modeset_commit_cdclk;
> +		dev_priv->display.set_cdclk = bxt_set_cdclk;
>  		dev_priv->display.modeset_calc_cdclk =
>  			bxt_modeset_calc_cdclk;
>  	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> -		dev_priv->display.modeset_commit_cdclk =
> -			skl_modeset_commit_cdclk;
> +		dev_priv->display.set_cdclk = skl_set_cdclk;
>  		dev_priv->display.modeset_calc_cdclk =
>  			skl_modeset_calc_cdclk;
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index fb3abb58b6ca..409537011b28 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12872,10 +12872,7 @@ static void intel_atomic_commit_tail(struct
> drm_atomic_state *state)
>  	if (intel_state->modeset) {
>  		drm_atomic_helper_update_legacy_modeset_state(state->dev,
> state);
>  
> -		if (dev_priv->display.modeset_commit_cdclk &&
> -		    !intel_cdclk_state_compare(&dev_priv->cdclk.hw,
> -					       &dev_priv->cdclk.actual))
> -			dev_priv->display.modeset_commit_cdclk(state);
> +		intel_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
>  
>  		/*
>  		 * SKL workaround: bspec recommends we disable the SAGV when
> we
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index d167ee458d63..40074827f01d 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1231,6 +1231,8 @@ void intel_update_cdclk(struct drm_i915_private
> *dev_priv);
>  void intel_update_rawclk(struct drm_i915_private *dev_priv);
>  bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
>  			       const struct intel_cdclk_state *b);
> +void intel_set_cdclk(struct drm_i915_private *dev_priv,
> +		     const struct intel_cdclk_state *cdclk_state);
>  
>  /* intel_display.c */
>  enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 14/14] drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c
  2016-12-19 17:28 ` [PATCH 14/14] drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c ville.syrjala
@ 2016-12-23 14:06   ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 40+ messages in thread
From: Ander Conselvan De Oliveira @ 2016-12-23 14:06 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Rodrigo Vivi

On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Move ilk_pipe_pixel_rate() next to its only caller
> (intel_crtc_compute_pixel_rate()).

Assuming a rebased patch 1,

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 35 +++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  1 -
>  drivers/gpu/drm/i915/intel_pm.c      | 33 ---------------------------------
>  3 files changed, 35 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 409537011b28..5e18a598117c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6229,6 +6229,41 @@ static bool intel_crtc_supports_double_wide(const
> struct intel_crtc *crtc)
>  		(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
>  }
>  
> +static uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state
> *pipe_config)
> +{
> +	uint32_t pixel_rate;
> +
> +	pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
> +
> +	/*
> +	 * We only use IF-ID interlacing. If we ever use
> +	 * PF-ID we'll need to adjust the pixel_rate here.
> +	 */
> +
> +	if (pipe_config->pch_pfit.enabled) {
> +		uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
> +		uint32_t pfit_size = pipe_config->pch_pfit.size;
> +
> +		pipe_w = pipe_config->pipe_src_w;
> +		pipe_h = pipe_config->pipe_src_h;
> +
> +		pfit_w = (pfit_size >> 16) & 0xFFFF;
> +		pfit_h = pfit_size & 0xFFFF;
> +		if (pipe_w < pfit_w)
> +			pipe_w = pfit_w;
> +		if (pipe_h < pfit_h)
> +			pipe_h = pfit_h;
> +
> +		if (WARN_ON(!pfit_w || !pfit_h))
> +			return pixel_rate;
> +
> +		pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
> +				     pfit_w * pfit_h);
> +	}
> +
> +	return pixel_rate;
> +}
> +
>  static void intel_crtc_compute_pixel_rate(struct intel_crtc_state
> *crtc_state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc-
> >dev);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index 40074827f01d..4fd03b73d863 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1791,7 +1791,6 @@ bool skl_wm_level_equals(const struct skl_wm_level *l1,
>  bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries,
>  				 const struct skl_ddb_entry *ddb,
>  				 int ignore);
> -uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
>  bool ilk_disable_lp_wm(struct drm_device *dev);
>  int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6);
>  static inline int intel_enable_rc6(void)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index fe522ec21502..cd81b51291d6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1701,39 +1701,6 @@ static void i845_update_wm(struct intel_crtc
> *unused_crtc)
>  	I915_WRITE(FW_BLC, fwater_lo);
>  }
>  
> -uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
> -{
> -	uint32_t pixel_rate;
> -
> -	pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
> -
> -	/* We only use IF-ID interlacing. If we ever use PF-ID we'll need to
> -	 * adjust the pixel_rate here. */
> -
> -	if (pipe_config->pch_pfit.enabled) {
> -		uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
> -		uint32_t pfit_size = pipe_config->pch_pfit.size;
> -
> -		pipe_w = pipe_config->pipe_src_w;
> -		pipe_h = pipe_config->pipe_src_h;
> -
> -		pfit_w = (pfit_size >> 16) & 0xFFFF;
> -		pfit_h = pfit_size & 0xFFFF;
> -		if (pipe_w < pfit_w)
> -			pipe_w = pfit_w;
> -		if (pipe_h < pfit_h)
> -			pipe_h = pfit_h;
> -
> -		if (WARN_ON(!pfit_w || !pfit_h))
> -			return pixel_rate;
> -
> -		pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
> -				     pfit_w * pfit_h);
> -	}
> -
> -	return pixel_rate;
> -}
> -
>  /* latency must be in 0.1us units. */
>  static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t
> latency)
>  {
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 11/14] drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk()
  2016-12-23 13:49   ` Ander Conselvan De Oliveira
@ 2016-12-23 14:07     ` Ville Syrjälä
  0 siblings, 0 replies; 40+ messages in thread
From: Ville Syrjälä @ 2016-12-23 14:07 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira; +Cc: intel-gfx, Rodrigo Vivi

On Fri, Dec 23, 2016 at 03:49:02PM +0200, Ander Conselvan De Oliveira wrote:
> On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Move the vlv_program_pfi_credits() into vlv_set_cdclk() and
> > chv_set_cdclk() so that we can neuter vlv_modeset_commit_cdclk().
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_cdclk.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> > b/drivers/gpu/drm/i915/intel_cdclk.c
> > index 11a0f3e122c3..fe7a9e3a4f29 100644
> > --- a/drivers/gpu/drm/i915/intel_cdclk.c
> > +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> > @@ -494,6 +494,8 @@ static void vlv_set_cdclk(struct drm_i915_private
> > *dev_priv,
> >  
> >  	mutex_unlock(&dev_priv->sb_lock);
> >  
> > +	vlv_program_pfi_credits(dev_priv);
> > +
> >  	intel_update_cdclk(dev_priv);
> >  }
> >  
> > @@ -533,6 +535,8 @@ static void chv_set_cdclk(struct drm_i915_private
> > *dev_priv,
> >  	}
> >  	mutex_unlock(&dev_priv->rps.hw_lock);
> >  
> > +	vlv_program_pfi_credits(dev_priv);
> > +
> >  	intel_update_cdclk(dev_priv);
> 
> Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
> 
> Can the vlv/chv register write in intel_update_cdclk() be moved to the set_cdclk() funcs too?

We'll still need to initialize it at driver load time. I supoose I could
also add it to the power well enable hook. IIRC this register probably
had some magic retention logic while the power well is off so that we
don't actually lose the state (the register is simply inaccessible
while the power well is down). So for normal power well activity we
wouldn't really need to rewrite the register every time, but I guess
there'd not be much harm in doing it anyway. But I'll have to double
check this stuff since I'm not 100% sure.

> 
> 
> >  }
> >  
> > @@ -1433,7 +1437,6 @@ static void vlv_modeset_commit_cdclk(struct
> > drm_atomic_state *old_state)
> >  	else
> >  		vlv_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
> >  
> > -	vlv_program_pfi_credits(dev_priv);
> >  
> >  	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> >  }
> 
> 

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

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

* Re: [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state
  2016-12-20 13:29     ` Ville Syrjälä
@ 2017-01-12 20:37       ` Rodrigo Vivi
  2017-01-13  9:50         ` Ville Syrjälä
  0 siblings, 1 reply; 40+ messages in thread
From: Rodrigo Vivi @ 2017-01-12 20:37 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Rodrigo Vivi

On Tue, Dec 20, 2016 at 03:29:54PM +0200, Ville Syrjälä wrote:
> On Tue, Dec 20, 2016 at 03:10:53PM +0200, Ander Conselvan De Oliveira wrote:
> > On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Rather than recomptuing the pipe pixel rate on demand everwhere, let's
> > > just stick the precomputed value into the crtc state.
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_display.c | 31 ++++++++++++++++++++++++++-----
> > >  drivers/gpu/drm/i915/intel_drv.h     |  2 ++
> > >  drivers/gpu/drm/i915/intel_fbc.c     |  3 +--
> > >  drivers/gpu/drm/i915/intel_pm.c      | 14 +++++++-------
> > >  4 files changed, 36 insertions(+), 14 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index 0b0d7e8be630..1d979041c52c 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > 
> > 
> > [...]
> > 
> > > @@ -16919,7 +16938,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
> >                 __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
> >                 memset(crtc_state, 0, sizeof(*crtc_state));
> >                 crtc_state->base.crtc = &crtc->base;
> >  
> >                 crtc_state->base.active = crtc_state->base.enable =
> >                         dev_priv->display.get_pipe_config(crtc, crtc_state);
> >  
> >                 crtc->base.enabled = crtc_state->base.enable;
> >                 crtc->active = crtc_state->base.active;
> >  
> >                 if (crtc_state->base.active) {
> > >  			dev_priv->active_crtcs |= 1 << crtc->pipe;
> > >  
> > >  			if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> > > -				pixclk = ilk_pipe_pixel_rate(crtc_state);
> > > +				pixclk = crtc_state->pixel_rate;
> > 
> > Aren't you reading 0 here, because of the memset above? As far as I can tell,
> > haswell_get_pipe_config() doesn't set crtc_state->pixel_rate.
> 
> Hmm, yeah. Which means this whole piece of min_pixclk[] code is in
> the wrong place. You can't know the pixel rate until you know the
> clock, and you don't know that until you've done the full readout
> (meaning the encoder .get_config() hooks have been called as well).

Apparently this is the only piece blocking this already reviewed series, right?

So, what are the plans? drop this patch and move with the other patches?


> 
> > 
> > >  			else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > >  				pixclk = crtc_state->base.adjusted_mode.crtc_clock;
> > >  			else
> > > @@ -17031,6 +17050,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
> > >  			 */
> > >  			crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
> > >  
> > > +			intel_crtc_compute_pixel_rate(crtc->config);
> > > +
> > >  			drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
> > >  			update_scanline_offset(crtc);
> > >  		}
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index f61ea43c7532..3969e786d566 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -541,6 +541,8 @@ struct intel_crtc_state {
> > >  	 * and get clipped at the edges. */
> > >  	int pipe_src_w, pipe_src_h;
> > >  
> > > +	unsigned int pixel_rate;
> > > +
> > 
> > Maybe add some comment about this parameter. This is not in kernel doc, but
> > having that already would probably make it easier for whoever does it in the
> > end.
> > 
> > Ander
> 
> -- 
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> 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] 40+ messages in thread

* Re: [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state
  2017-01-12 20:37       ` Rodrigo Vivi
@ 2017-01-13  9:50         ` Ville Syrjälä
  0 siblings, 0 replies; 40+ messages in thread
From: Ville Syrjälä @ 2017-01-13  9:50 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Rodrigo Vivi

On Thu, Jan 12, 2017 at 12:37:46PM -0800, Rodrigo Vivi wrote:
> On Tue, Dec 20, 2016 at 03:29:54PM +0200, Ville Syrjälä wrote:
> > On Tue, Dec 20, 2016 at 03:10:53PM +0200, Ander Conselvan De Oliveira wrote:
> > > On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@linux.intel.com wrote:
> > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > 
> > > > Rather than recomptuing the pipe pixel rate on demand everwhere, let's
> > > > just stick the precomputed value into the crtc state.
> > > > 
> > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_display.c | 31 ++++++++++++++++++++++++++-----
> > > >  drivers/gpu/drm/i915/intel_drv.h     |  2 ++
> > > >  drivers/gpu/drm/i915/intel_fbc.c     |  3 +--
> > > >  drivers/gpu/drm/i915/intel_pm.c      | 14 +++++++-------
> > > >  4 files changed, 36 insertions(+), 14 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > > index 0b0d7e8be630..1d979041c52c 100644
> > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > 
> > > 
> > > [...]
> > > 
> > > > @@ -16919,7 +16938,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
> > >                 __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
> > >                 memset(crtc_state, 0, sizeof(*crtc_state));
> > >                 crtc_state->base.crtc = &crtc->base;
> > >  
> > >                 crtc_state->base.active = crtc_state->base.enable =
> > >                         dev_priv->display.get_pipe_config(crtc, crtc_state);
> > >  
> > >                 crtc->base.enabled = crtc_state->base.enable;
> > >                 crtc->active = crtc_state->base.active;
> > >  
> > >                 if (crtc_state->base.active) {
> > > >  			dev_priv->active_crtcs |= 1 << crtc->pipe;
> > > >  
> > > >  			if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> > > > -				pixclk = ilk_pipe_pixel_rate(crtc_state);
> > > > +				pixclk = crtc_state->pixel_rate;
> > > 
> > > Aren't you reading 0 here, because of the memset above? As far as I can tell,
> > > haswell_get_pipe_config() doesn't set crtc_state->pixel_rate.
> > 
> > Hmm, yeah. Which means this whole piece of min_pixclk[] code is in
> > the wrong place. You can't know the pixel rate until you know the
> > clock, and you don't know that until you've done the full readout
> > (meaning the encoder .get_config() hooks have been called as well).
> 
> Apparently this is the only piece blocking this already reviewed series, right?

Not sure. I'll have to go over it again to see what was said. At least
adding some docs for intel_cdclk.c was requested.

> 
> So, what are the plans? drop this patch and move with the other patches?

I think I pushed the fix to move the min_pixclk[] handling to happen a
little later, so all I should have to do is rebase this patch and it
should all be good.

But as usual I have a few too many irons in the fire, so I haven't
managed to get back to this series yet.

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

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

* [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk()
  2016-12-19 12:34 [PATCH 00/14] drm/i915: Introduce intel_cdclk_state ville.syrjala
@ 2016-12-19 12:34 ` ville.syrjala
  0 siblings, 0 replies; 40+ messages in thread
From: ville.syrjala @ 2016-12-19 12:34 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

ilk_max_pixel_rate() will now give the "correct" pixel rate for all
platforms, so let's kill rename it to intel_max_pixel_rate() and kill
off intel_mode_max_pixclk().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 41 ++++++------------------------------
 1 file changed, 6 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1d979041c52c..1e3f173a70e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -123,7 +123,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
 static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
-static int ilk_max_pixel_rate(struct drm_atomic_state *state);
+static int intel_max_pixel_rate(struct drm_atomic_state *state);
 static int glk_calc_cdclk(int max_pixclk);
 static int bxt_calc_cdclk(int max_pixclk);
 
@@ -6566,40 +6566,11 @@ static int bxt_calc_cdclk(int max_pixclk)
 		return 144000;
 }
 
-/* Compute the max pixel clock for new configuration. */
-static int intel_mode_max_pixclk(struct drm_device *dev,
-				 struct drm_atomic_state *state)
-{
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	unsigned max_pixclk = 0, i;
-	enum pipe pipe;
-
-	memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
-	       sizeof(intel_state->min_pixclk));
-
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		int pixclk = 0;
-
-		if (crtc_state->enable)
-			pixclk = crtc_state->adjusted_mode.crtc_clock;
-
-		intel_state->min_pixclk[i] = pixclk;
-	}
-
-	for_each_pipe(dev_priv, pipe)
-		max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
-
-	return max_pixclk;
-}
-
 static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int max_pixclk = intel_mode_max_pixclk(dev, state);
+	int max_pixclk = intel_max_pixel_rate(state);
 	struct intel_atomic_state *intel_state =
 		to_intel_atomic_state(state);
 
@@ -6615,7 +6586,7 @@ static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
 static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	int max_pixclk = ilk_max_pixel_rate(state);
+	int max_pixclk = intel_max_pixel_rate(state);
 	struct intel_atomic_state *intel_state =
 		to_intel_atomic_state(state);
 	int cdclk;
@@ -10290,7 +10261,7 @@ static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
 }
 
 /* compute the max rate for new configuration */
-static int ilk_max_pixel_rate(struct drm_atomic_state *state)
+static int intel_max_pixel_rate(struct drm_atomic_state *state)
 {
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
@@ -10422,7 +10393,7 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	int max_pixclk = ilk_max_pixel_rate(state);
+	int max_pixclk = intel_max_pixel_rate(state);
 	int cdclk;
 
 	/*
@@ -10458,7 +10429,7 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	const int max_pixclk = ilk_max_pixel_rate(state);
+	const int max_pixclk = intel_max_pixel_rate(state);
 	int vco = intel_state->cdclk_pll_vco;
 	int cdclk;
 
-- 
2.10.2

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

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

end of thread, other threads:[~2017-01-13  9:50 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-19 17:28 [PATCH v2 00/14] drm/i915: Introduce intel_cdclk_state (v2) ville.syrjala
2016-12-19 17:28 ` [PATCH 01/14] drm/i915: Store the pipe pixel rate in the crtc state ville.syrjala
2016-12-20 13:10   ` Ander Conselvan De Oliveira
2016-12-20 13:29     ` Ville Syrjälä
2017-01-12 20:37       ` Rodrigo Vivi
2017-01-13  9:50         ` Ville Syrjälä
2016-12-19 17:28 ` [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk() ville.syrjala
2016-12-20 13:22   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH 03/14] drm/i915: s/get_display_clock_speed/get_cdclk/ ville.syrjala
2016-12-20 13:27   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH 04/14] drm/i915: Clean up the .get_cdclk() assignment if ladder ville.syrjala
2016-12-20 13:42   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c ville.syrjala
2016-12-22 13:10   ` Ander Conselvan De Oliveira
2016-12-22 13:16     ` Joonas Lahtinen
2016-12-19 17:28 ` [PATCH 06/14] drm/i915: Pass computed vco to bxt_set_cdclk() ville.syrjala
2016-12-22 13:22   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH v2 07/14] drm/i915: Start moving the cdclk stuff into a distinct state structure ville.syrjala
2016-12-22 14:14   ` Ander Conselvan De Oliveira
2016-12-22 14:33     ` Ville Syrjälä
2016-12-23  9:09       ` Ander Conselvan De Oliveira
2016-12-23 12:27         ` Ville Syrjälä
2016-12-23 13:07           ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH v2 08/14] drm/i915: Track full cdclk state for the logical and actual cdclk frequencies ville.syrjala
2016-12-23 11:53   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH v2 09/14] drm/i915: Pass dev_priv to remainder of the cdclk functions ville.syrjala
2016-12-23 12:01   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH v2 10/14] drm/i915: Pass the cdclk state to the set_cdclk() functions ville.syrjala
2016-12-23 13:43   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH 11/14] drm/i915: Move PFI credit reprogramming into vlv/chv_set_cdclk() ville.syrjala
2016-12-23 13:49   ` Ander Conselvan De Oliveira
2016-12-23 14:07     ` Ville Syrjälä
2016-12-19 17:28 ` [PATCH 12/14] drm/i915: Nuke the VLV/CHV PFI programming power domain workaround ville.syrjala
2016-12-23 13:52   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH v2 13/14] drm/i915: Replace the .modeset_commit_cdclk() hook with a more direct .set_cdclk() hook ville.syrjala
2016-12-23 14:03   ` Ander Conselvan De Oliveira
2016-12-19 17:28 ` [PATCH 14/14] drm/i915: Move ilk_pipe_pixel_rate() to intel_display.c ville.syrjala
2016-12-23 14:06   ` Ander Conselvan De Oliveira
2016-12-19 18:15 ` ✓ Fi.CI.BAT: success for drm/i915: Introduce intel_cdclk_state (rev2) Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2016-12-19 12:34 [PATCH 00/14] drm/i915: Introduce intel_cdclk_state ville.syrjala
2016-12-19 12:34 ` [PATCH 02/14] drm/i915: Nuke intel_mode_max_pixclk() ville.syrjala

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.