summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_cdclk.c
diff options
context:
space:
mode:
authorVille Syrjälä2017-10-24 11:52:14 +0200
committerVille Syrjälä2017-10-25 12:40:52 +0200
commit53e9bf5e8159765e0dc807567180afd0b389f149 (patch)
tree3c0a0ad64eeb2e560da342b52bbefe96a8479684 /drivers/gpu/drm/i915/intel_cdclk.c
parentdrm/i915: Use cdclk_state->voltage on CNL (diff)
downloadkernel-qcow2-linux-53e9bf5e8159765e0dc807567180afd0b389f149.tar.gz
kernel-qcow2-linux-53e9bf5e8159765e0dc807567180afd0b389f149.tar.xz
kernel-qcow2-linux-53e9bf5e8159765e0dc807567180afd0b389f149.zip
drm/i915: Adjust system agent voltage on CNL if required by DDI ports
On CNL we may need to bump up the system agent voltage not only due to CDCLK but also when driving DDI port with a sufficiently high clock. To that end start tracking the minimum acceptable voltage for each crtc. We do the tracking via crtcs because we don't have any kind of encoder state. Also there's no downside to doing it this way, and it matches how we track cdclk requirements on account of pixel rate. v2: Allow disabled crtcs to use the min voltage Add IS_CNL check to intel_ddi_compute_min_voltage() since we're using CNL specific values there s/intel_compute_min_voltage/cnl_compute_min_voltage/ since the function makes hw specific assumptions about the voltage values v3: Drop the test hack leftovers from skl_modeset_calc_cdclk() v4: s/voltage/voltage_level/ (Rodrigo) Replace DPLL DVFS FIXMEs with an explanation why we don't do anything there (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: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171024095216.1638-9-ville.syrjala@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/intel_cdclk.c')
-rw-r--r--drivers/gpu/drm/i915/intel_cdclk.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 210e79193fe6..4ca4a34b7bfa 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -1665,6 +1665,12 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv,
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 int cnl_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
@@ -1934,6 +1940,43 @@ static int intel_compute_min_cdclk(struct drm_atomic_state *state)
return min_cdclk;
}
+/*
+ * Note that this functions assumes that 0 is
+ * the lowest voltage value, and higher values
+ * correspond to increasingly higher voltages.
+ *
+ * Should that relationship no longer hold on
+ * future platforms this code will need to be
+ * adjusted.
+ */
+static u8 cnl_compute_min_voltage_level(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct intel_crtc *crtc;
+ struct intel_crtc_state *crtc_state;
+ u8 min_voltage_level;
+ int i;
+ enum pipe pipe;
+
+ memcpy(state->min_voltage_level, dev_priv->min_voltage_level,
+ sizeof(state->min_voltage_level));
+
+ for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc_state->base.enable)
+ state->min_voltage_level[i] =
+ crtc_state->min_voltage_level;
+ else
+ state->min_voltage_level[i] = 0;
+ }
+
+ min_voltage_level = 0;
+ for_each_pipe(dev_priv, pipe)
+ min_voltage_level = max(state->min_voltage_level[pipe],
+ min_voltage_level);
+
+ return min_voltage_level;
+}
+
static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
{
struct drm_i915_private *dev_priv = to_i915(state->dev);
@@ -2097,7 +2140,8 @@ static int cnl_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 =
- cnl_calc_voltage_level(cdclk);
+ max(cnl_calc_voltage_level(cdclk),
+ cnl_compute_min_voltage_level(intel_state));
if (!intel_state->active_crtcs) {
cdclk = cnl_calc_cdclk(0);