Commit 64600bd5 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Start tracking voltage level in the cdclk state

For CNL we'll need to start considering the port clocks when we select
the voltage level for the system agent. To that end start tracking the
voltage in the cdclk state (since that already has to adjust it).

v2: s/voltage/voltage_level/ (Rodrigo)

Cc: Mika Kahola <mika.kahola@intel.com>
Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171024095216.1638-3-ville.syrjala@linux.intel.com
parent 2b58417f
...@@ -2228,6 +2228,7 @@ struct i915_oa_ops { ...@@ -2228,6 +2228,7 @@ struct i915_oa_ops {
struct intel_cdclk_state { struct intel_cdclk_state {
unsigned int cdclk, vco, ref; unsigned int cdclk, vco, ref;
u8 voltage_level;
}; };
struct drm_i915_private { struct drm_i915_private {
......
...@@ -1690,17 +1690,34 @@ void cnl_uninit_cdclk(struct drm_i915_private *dev_priv) ...@@ -1690,17 +1690,34 @@ void cnl_uninit_cdclk(struct drm_i915_private *dev_priv)
} }
/** /**
* intel_cdclk_state_compare - Determine if two CDCLK states differ * intel_cdclk_needs_modeset - Determine if two CDCLK states require a modeset on all pipes
* @a: first CDCLK state * @a: first CDCLK state
* @b: second CDCLK state * @b: second CDCLK state
* *
* Returns: * Returns:
* True if the CDCLK states are identical, false if they differ. * True if the CDCLK states require pipes to be off during reprogramming, false if not.
*/ */
bool intel_cdclk_state_compare(const struct intel_cdclk_state *a, bool intel_cdclk_needs_modeset(const struct intel_cdclk_state *a,
const struct intel_cdclk_state *b) const struct intel_cdclk_state *b)
{ {
return memcmp(a, b, sizeof(*a)) == 0; return a->cdclk != b->cdclk ||
a->vco != b->vco ||
a->ref != b->ref;
}
/**
* intel_cdclk_changed - Determine if two CDCLK states are different
* @a: first CDCLK state
* @b: second CDCLK state
*
* Returns:
* True if the CDCLK states don't match, false if they do.
*/
bool intel_cdclk_changed(const struct intel_cdclk_state *a,
const struct intel_cdclk_state *b)
{
return intel_cdclk_needs_modeset(a, b) ||
a->voltage_level != b->voltage_level;
} }
/** /**
...@@ -1714,15 +1731,15 @@ bool intel_cdclk_state_compare(const struct intel_cdclk_state *a, ...@@ -1714,15 +1731,15 @@ bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
void intel_set_cdclk(struct drm_i915_private *dev_priv, void intel_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_state *cdclk_state) const struct intel_cdclk_state *cdclk_state)
{ {
if (intel_cdclk_state_compare(&dev_priv->cdclk.hw, cdclk_state)) if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_state))
return; return;
if (WARN_ON_ONCE(!dev_priv->display.set_cdclk)) if (WARN_ON_ONCE(!dev_priv->display.set_cdclk))
return; return;
DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz, VCO %d kHz, ref %d kHz\n", DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz, VCO %d kHz, ref %d kHz, voltage_level %d\n",
cdclk_state->cdclk, cdclk_state->vco, cdclk_state->cdclk, cdclk_state->vco,
cdclk_state->ref); cdclk_state->ref, cdclk_state->voltage_level);
dev_priv->display.set_cdclk(dev_priv, cdclk_state); dev_priv->display.set_cdclk(dev_priv, cdclk_state);
} }
......
...@@ -11931,7 +11931,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) ...@@ -11931,7 +11931,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
* holding all the crtc locks, even if we don't end up * holding all the crtc locks, even if we don't end up
* touching the hardware * touching the hardware
*/ */
if (!intel_cdclk_state_compare(&dev_priv->cdclk.logical, if (intel_cdclk_changed(&dev_priv->cdclk.logical,
&intel_state->cdclk.logical)) { &intel_state->cdclk.logical)) {
ret = intel_lock_all_pipes(state); ret = intel_lock_all_pipes(state);
if (ret < 0) if (ret < 0)
...@@ -11939,7 +11939,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) ...@@ -11939,7 +11939,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
} }
/* All pipes must be switched off while we change the cdclk. */ /* All pipes must be switched off while we change the cdclk. */
if (!intel_cdclk_state_compare(&dev_priv->cdclk.actual, if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual,
&intel_state->cdclk.actual)) { &intel_state->cdclk.actual)) {
ret = intel_modeset_all_pipes(state); ret = intel_modeset_all_pipes(state);
if (ret < 0) if (ret < 0)
......
...@@ -1323,7 +1323,9 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); ...@@ -1323,7 +1323,9 @@ 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_max_cdclk(struct drm_i915_private *dev_priv);
void intel_update_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); void intel_update_rawclk(struct drm_i915_private *dev_priv);
bool intel_cdclk_state_compare(const struct intel_cdclk_state *a, bool intel_cdclk_needs_modeset(const struct intel_cdclk_state *a,
const struct intel_cdclk_state *b);
bool intel_cdclk_changed(const struct intel_cdclk_state *a,
const struct intel_cdclk_state *b); const struct intel_cdclk_state *b);
void intel_set_cdclk(struct drm_i915_private *dev_priv, void intel_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_state *cdclk_state); const struct intel_cdclk_state *cdclk_state);
......
...@@ -705,7 +705,8 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, ...@@ -705,7 +705,8 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
dev_priv->display.get_cdclk(dev_priv, &cdclk_state); dev_priv->display.get_cdclk(dev_priv, &cdclk_state);
WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state)); /* Can't read out voltage_level so can't use intel_cdclk_changed() */
WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw, &cdclk_state));
gen9_assert_dbuf_enabled(dev_priv); gen9_assert_dbuf_enabled(dev_priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment