From: Mika Kahola <mika.kahola@intel.com>
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH v4 10/12] drm/i915: HSW cdclk support
Date: Fri, 22 May 2015 11:22:40 +0300 [thread overview]
Message-ID: <1432282962-3530-11-git-send-email-mika.kahola@intel.com> (raw)
In-Reply-To: <1432282962-3530-1-git-send-email-mika.kahola@intel.com>
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Implement support for changing the cdclk frequency during runtime on
HSW. VLV/CHV already have support for this, so we can follow their
example for the most part. Only the actual hardware programming differs,
the rest is pretty much the same.
The pipe pixel rate stuff is handled a bit differently for now due to
the difference in pch vs. gmch pfit handling. Eventually we should unify
that part to eliminate what is essentially duplicated code.
v2: Grab rps.hw_lock around sandybridge_pcode_write()
v3: Rebase due to power well vs. .global_resources() reordering
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
v3: Rebased to the latest
v4: Reformatting 'haswell_modeset_global_pipes' function to
support atomic state
Signed-off-by: Mika Kahola <mika.kahola@intel.com>
Author: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 3 +
drivers/gpu/drm/i915/intel_display.c | 161 +++++++++++++++++++++++++++++++++--
2 files changed, 159 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 14366c8..015fe12 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6701,6 +6701,7 @@ enum skl_disp_power_wells {
#define GEN6_PCODE_READ_RC6VIDS 0x5
#define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5)
#define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245)
+#define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17
#define GEN9_PCODE_READ_MEM_LATENCY 0x6
#define GEN9_MEM_LATENCY_LEVEL_MASK 0xFF
#define GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT 8
@@ -7159,10 +7160,12 @@ enum skl_disp_power_wells {
#define LCPLL_PLL_LOCK (1<<30)
#define LCPLL_CLK_FREQ_MASK (3<<26)
#define LCPLL_CLK_FREQ_450 (0<<26)
+#define LCPLL_CLK_FREQ_ALT_HSW (1<<26) /* 337.5 (ULX) or 540 */
#define LCPLL_CLK_FREQ_54O_BDW (1<<26)
#define LCPLL_CLK_FREQ_337_5_BDW (2<<26)
#define LCPLL_CLK_FREQ_675_BDW (3<<26)
#define LCPLL_CD_CLOCK_DISABLE (1<<25)
+#define LCPLL_ROOT_CD_CLOCK_DISABLE (1<<24)
#define LCPLL_CD2X_CLOCK_DISABLE (1<<23)
#define LCPLL_POWER_DOWN_ALLOW (1<<22)
#define LCPLL_CD_SOURCE_FCLK (1<<21)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index febf993..556d0ec7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5545,7 +5545,16 @@ static void intel_update_max_cdclk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (IS_VALLEYVIEW(dev)) {
+ if (IS_HASWELL(dev)) {
+ if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
+ dev_priv->max_cdclk_freq = 450000;
+ else if (IS_HSW_ULX(dev))
+ dev_priv->max_cdclk_freq = 337500;
+ else if (IS_HSW_ULT(dev))
+ dev_priv->max_cdclk_freq = 450000;
+ else
+ dev_priv->max_cdclk_freq = 540000;
+ } else if (IS_VALLEYVIEW(dev)) {
dev_priv->max_cdclk_freq = 400000;
} else {
/* otherwise assume cdclk is fixed */
@@ -9404,6 +9413,139 @@ static void broxton_modeset_global_resources(struct drm_atomic_state *old_state)
broxton_set_cdclk(dev, req_cdclk);
}
+/* compute the max rate for new configuration */
+static int ilk_max_pixel_rate(struct drm_i915_private *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+ struct intel_crtc *crtc;
+ int max_pixel_rate = 0;
+
+ for_each_intel_crtc(dev, crtc) {
+ if (crtc->new_enabled)
+ max_pixel_rate = max((int)max_pixel_rate,
+ (int)ilk_pipe_pixel_rate(crtc->config));
+ }
+
+ return max_pixel_rate;
+}
+
+static int haswell_calc_cdclk(struct drm_i915_private *dev_priv,
+ int max_pixel_rate)
+{
+ int cdclk;
+
+ /*
+ * FIXME should also account for plane ratio
+ * once 64bpp pixel formats are supported.
+ */
+ if (max_pixel_rate > 450000)
+ cdclk = 540000;
+ else if (max_pixel_rate > 337500 || !IS_HSW_ULX(dev_priv))
+ cdclk = 450000;
+ else
+ cdclk = 337500;
+
+ /*
+ * 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;
+ }
+
+ return cdclk;
+}
+
+static void haswell_set_cdclk(struct drm_device *dev, int cdclk)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t val;
+
+ 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;
+
+ val = I915_READ(LCPLL_CTL);
+ val &= ~LCPLL_CLK_FREQ_MASK;
+
+ switch (cdclk) {
+ case 450000:
+ val |= LCPLL_CLK_FREQ_450;
+ break;
+ case 337500:
+ case 540000:
+ val |= LCPLL_CLK_FREQ_ALT_HSW;
+ break;
+ default:
+ WARN(1, "invalid cdclk frequency\n");
+ return;
+ }
+
+ I915_WRITE(LCPLL_CTL, val);
+
+ if (IS_HSW_ULX(dev)) {
+ mutex_lock(&dev_priv->rps.hw_lock);
+ sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
+ cdclk == 337500);
+ mutex_unlock(&dev_priv->rps.hw_lock);
+ }
+
+ intel_update_cdclk(dev);
+
+ WARN(cdclk != dev_priv->cdclk_freq,
+ "cdclk requested %d kHz but got %d kHz\n",
+ cdclk, dev_priv->cdclk_freq);
+}
+
+static int haswell_modeset_global_pipes(struct drm_atomic_state *state)
+{
+ struct drm_i915_private *dev_priv = to_i915(state->dev);
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ int max_pixclk = ilk_max_pixel_rate(dev_priv);
+ int cdclk, i;
+
+ cdclk = haswell_calc_cdclk(dev_priv, max_pixclk);
+
+ if (cdclk == dev_priv->cdclk_freq)
+ return 0;
+
+ /* add all active pipes to the state */
+ for_each_crtc(state->dev, crtc) {
+ if (!crtc->state->enable)
+ continue;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+ }
+
+ /* disable/enable all currently active pipes while we change cdclk */
+ for_each_crtc_in_state(state, crtc, crtc_state, i)
+ if (crtc_state->enable)
+ crtc_state->mode_changed = true;
+
+ return 0;
+}
+
+static void haswell_modeset_global_resources(struct drm_atomic_state *state)
+{
+ struct drm_device *dev = state->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int max_pixel_rate = ilk_max_pixel_rate(dev_priv);
+ int req_cdclk = haswell_calc_cdclk(dev_priv, max_pixel_rate);
+
+ if (req_cdclk != dev_priv->cdclk_freq) {
+ haswell_set_cdclk(dev, req_cdclk);
+ }
+}
+
static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state)
{
@@ -12582,10 +12724,16 @@ static int __intel_set_mode_checks(struct drm_atomic_state *state)
* mode set on this crtc. For other crtcs we need to use the
* adjusted_mode bits in the crtc directly.
*/
- if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) {
- ret = valleyview_modeset_global_pipes(state);
- if (ret)
- return ret;
+ if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev) || IS_HASWELL(dev)) {
+ if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) {
+ ret = valleyview_modeset_global_pipes(state);
+ if (ret)
+ return ret;
+ } else {
+ ret = haswell_modeset_global_pipes(state);
+ if (ret)
+ return ret;
+ }
}
ret = __intel_set_mode_setup_plls(state);
@@ -14468,6 +14616,9 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
dev_priv->display.fdi_link_train = hsw_fdi_link_train;
+ if (IS_HASWELL(dev))
+ dev_priv->display.modeset_global_resources =
+ haswell_modeset_global_resources;
} else if (IS_VALLEYVIEW(dev)) {
dev_priv->display.modeset_global_resources =
valleyview_modeset_global_resources;
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2015-05-22 8:22 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-22 8:22 [PATCH v4 00/12] All sort of cdclk stuff Mika Kahola
2015-05-22 8:22 ` [PATCH v4 01/12] drm/i915: Fix i855 get_display_clock_speed Mika Kahola
2015-05-28 18:12 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 02/12] drm/i915: Fix 852GM/GMV cdclk Mika Kahola
2015-05-28 18:16 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 03/12] drm/i915: Add cdclk extraction for g33, g965gm and g4x Mika Kahola
2015-05-28 18:17 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 04/12] drm/i915: Warn when cdclk for the platforms is not known Mika Kahola
2015-05-28 18:19 ` Damien Lespiau
2015-05-29 7:57 ` Daniel Vetter
2015-05-22 8:22 ` [PATCH v4 05/12] drm/i915: Cache current cdclk frequency in dev_priv Mika Kahola
2015-05-28 18:24 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 06/12] drm/i915: Use cached cdclk value Mika Kahola
2015-05-28 18:27 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 07/12] drm/i915: Unify ilk and hsw .get_aux_clock_divider Mika Kahola
2015-05-28 18:31 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 8/8] drm/i915: Store max cdclk value in dev_priv Mika Kahola
2015-05-28 18:32 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 09/12] drm/i915: Don't enable IPS when pixel rate exceeds 95% Mika Kahola
2015-05-28 18:35 ` Damien Lespiau
2015-05-22 8:22 ` Mika Kahola [this message]
2015-05-29 11:30 ` [PATCH v4 10/12] drm/i915: HSW cdclk support Damien Lespiau
2015-05-29 12:06 ` Kahola, Mika
2015-05-29 12:56 ` Damien Lespiau
2015-05-29 13:51 ` Ville Syrjälä
2015-05-22 8:22 ` [PATCH v4 11/12] drm/i915: Add IS_BDW_ULX Mika Kahola
2015-05-29 11:33 ` Damien Lespiau
2015-05-22 8:22 ` [PATCH v4 12/12] drm/i915: BDW clock change support Mika Kahola
2015-05-29 11:45 ` Damien Lespiau
2015-05-22 8:41 ` [PATCH v4 00/12] All sort of cdclk stuff Jani Nikula
2015-05-22 8:46 ` Jani Nikula
2015-05-27 21:49 ` Joe Konno
2015-05-28 15:29 ` Damien Lespiau
2015-05-28 16:01 ` Daniel Vetter
2015-05-28 17:11 ` Joe Konno
2015-05-28 17:20 ` Damien Lespiau
2015-05-28 17:17 ` Jani Nikula
2015-05-28 17:28 ` Damien Lespiau
2015-05-28 17:40 ` Jani Nikula
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1432282962-3530-11-git-send-email-mika.kahola@intel.com \
--to=mika.kahola@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.