|
@@ -1871,11 +1871,35 @@ static void icl_set_cdclk(struct drm_i915_private *dev_priv,
|
|
|
skl_cdclk_decimal(cdclk));
|
|
|
|
|
|
mutex_lock(&dev_priv->pcu_lock);
|
|
|
- /* TODO: add proper DVFS support. */
|
|
|
- sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, 2);
|
|
|
+ sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
|
|
+ cdclk_state->voltage_level);
|
|
|
mutex_unlock(&dev_priv->pcu_lock);
|
|
|
|
|
|
intel_update_cdclk(dev_priv);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Can't read out the voltage level :(
|
|
|
+ * Let's just assume everything is as expected.
|
|
|
+ */
|
|
|
+ dev_priv->cdclk.hw.voltage_level = cdclk_state->voltage_level;
|
|
|
+}
|
|
|
+
|
|
|
+static u8 icl_calc_voltage_level(int cdclk)
|
|
|
+{
|
|
|
+ switch (cdclk) {
|
|
|
+ case 50000:
|
|
|
+ case 307200:
|
|
|
+ case 312000:
|
|
|
+ return 0;
|
|
|
+ case 556800:
|
|
|
+ case 552000:
|
|
|
+ return 1;
|
|
|
+ default:
|
|
|
+ MISSING_CASE(cdclk);
|
|
|
+ case 652800:
|
|
|
+ case 648000:
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void icl_get_cdclk(struct drm_i915_private *dev_priv,
|
|
@@ -1909,7 +1933,7 @@ static void icl_get_cdclk(struct drm_i915_private *dev_priv,
|
|
|
*/
|
|
|
cdclk_state->vco = 0;
|
|
|
cdclk_state->cdclk = cdclk_state->bypass;
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
|
|
@@ -1918,6 +1942,14 @@ static void icl_get_cdclk(struct drm_i915_private *dev_priv,
|
|
|
WARN_ON((val & BXT_CDCLK_CD2X_DIV_SEL_MASK) != 0);
|
|
|
|
|
|
cdclk_state->cdclk = cdclk_state->vco / 2;
|
|
|
+
|
|
|
+out:
|
|
|
+ /*
|
|
|
+ * Can't read this out :( Let's assume it's
|
|
|
+ * at least what the CDCLK frequency requires.
|
|
|
+ */
|
|
|
+ cdclk_state->voltage_level =
|
|
|
+ icl_calc_voltage_level(cdclk_state->cdclk);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1960,6 +1992,8 @@ sanitize:
|
|
|
sanitized_state.cdclk = icl_calc_cdclk(0, sanitized_state.ref);
|
|
|
sanitized_state.vco = icl_calc_cdclk_pll_vco(dev_priv,
|
|
|
sanitized_state.cdclk);
|
|
|
+ sanitized_state.voltage_level =
|
|
|
+ icl_calc_voltage_level(sanitized_state.cdclk);
|
|
|
|
|
|
icl_set_cdclk(dev_priv, &sanitized_state);
|
|
|
}
|
|
@@ -1977,6 +2011,7 @@ void icl_uninit_cdclk(struct drm_i915_private *dev_priv)
|
|
|
|
|
|
cdclk_state.cdclk = cdclk_state.bypass;
|
|
|
cdclk_state.vco = 0;
|
|
|
+ cdclk_state.voltage_level = icl_calc_voltage_level(cdclk_state.cdclk);
|
|
|
|
|
|
icl_set_cdclk(dev_priv, &cdclk_state);
|
|
|
}
|
|
@@ -2480,6 +2515,9 @@ static int icl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
|
|
|
intel_state->cdclk.logical.vco = vco;
|
|
|
intel_state->cdclk.logical.cdclk = cdclk;
|
|
|
+ intel_state->cdclk.logical.voltage_level =
|
|
|
+ max(icl_calc_voltage_level(cdclk),
|
|
|
+ cnl_compute_min_voltage_level(intel_state));
|
|
|
|
|
|
if (!intel_state->active_crtcs) {
|
|
|
cdclk = icl_calc_cdclk(0, ref);
|
|
@@ -2487,6 +2525,8 @@ static int icl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
|
|
|
intel_state->cdclk.actual.vco = vco;
|
|
|
intel_state->cdclk.actual.cdclk = cdclk;
|
|
|
+ intel_state->cdclk.actual.voltage_level =
|
|
|
+ icl_calc_voltage_level(cdclk);
|
|
|
} else {
|
|
|
intel_state->cdclk.actual = intel_state->cdclk.logical;
|
|
|
}
|