summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_ddi.c
diff options
context:
space:
mode:
authorDamien Lespiau <damien.lespiau@intel.com>2015-05-21 18:37:48 +0300
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-05-21 23:50:15 +0300
commit5d96d8afcfbb1500272756747e0bfcdbebf3b070 (patch)
tree4d1141ab6de255d787d175dcb27ddc9e97a118ea /drivers/gpu/drm/i915/intel_ddi.c
parente61b995841e6d165b77209c2bdf9c96ae0c16b89 (diff)
downloadlinux-5d96d8afcfbb1500272756747e0bfcdbebf3b070.tar.xz
drm/i915/skl: Deinit/init the display at suspend/resume
We need to re-init the display hardware when going out of suspend. This includes: - Hooking the PCH to the reset logic - Restoring CDCDLK - Enabling the DDB power Among those, only the CDCDLK one is a bit tricky. There's some complexity in that: - DPLL0 (which is the source for CDCLK) has two VCOs, each with a set of supported frequencies. As eDP also uses DPLL0 for its link rate, once DPLL0 is on, we restrict the possible eDP link rates the chosen VCO. - CDCLK also limits the bandwidth available to push pixels. So, as a first step, this commit restore what the BIOS set, until I can do more testing. In case that's of interest for the reviewer, I've unit tested the function that derives the decimal frequency field: #include <stdio.h> #include <stdint.h> #include <assert.h> #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) static const struct dpll_freq { unsigned int freq; unsigned int decimal; } freqs[] = { { .freq = 308570, .decimal = 0b01001100111}, { .freq = 337500, .decimal = 0b01010100001}, { .freq = 432000, .decimal = 0b01101011110}, { .freq = 450000, .decimal = 0b01110000010}, { .freq = 540000, .decimal = 0b10000110110}, { .freq = 617140, .decimal = 0b10011010000}, { .freq = 675000, .decimal = 0b10101000100}, }; static void intbits(unsigned int v) { int i; for(i = 10; i >= 0; i--) putchar('0' + ((v >> i) & 1)); } static unsigned int freq_decimal(unsigned int freq /* in kHz */) { return (freq - 1000) / 500; } static void test_freq(const struct dpll_freq *entry) { unsigned int decimal = freq_decimal(entry->freq); printf("freq: %d, expected: ", entry->freq); intbits(entry->decimal); printf(", got: "); intbits(decimal); putchar('\n'); assert(decimal == entry->decimal); } int main(int argc, char **argv) { int i; for (i = 0; i < ARRAY_SIZE(freqs); i++) test_freq(&freqs[i]); return 0; } v2: - Rebase on top of -nightly - Use (freq - 1000) / 500 for the decimal frequency (Ville) - Fix setting the enable bit of HSW_NDE_RSTWRN_OPT (Ville) - Rename skl_display_{resume,suspend} to skl_{init,uninit}_cdclk to be consistent with the BXT code (Ville) - Store boot CDCLK in ddi_pll_init (Ville) - Merge dev_priv's skl_boot_cdclk into cdclk_freq - Use LCPLL_PLL_LOCK instead of (1 << 30) (Ville) - Replace various '0' by SKL_DPLL0 to be a bit more explicit that we're programming DPLL0 - Busy poll the PCU before doing the frequency change. It takes about 3/4 cycles, each separated by 10us, to get the ACK from the CPU (Ville) v3: - Restore dev_priv->skl_boot_cdclk, leaving unification with dev_priv->cdclk_freq for a later patch (Daniel, Ville) Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index d602db25eb33..cacb07b7a8f1 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2510,6 +2510,7 @@ void intel_ddi_pll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t val = I915_READ(LCPLL_CTL);
+ int cdclk_freq;
if (IS_SKYLAKE(dev))
skl_shared_dplls_init(dev_priv);
@@ -2518,12 +2519,15 @@ void intel_ddi_pll_init(struct drm_device *dev)
else
hsw_shared_dplls_init(dev_priv);
- DRM_DEBUG_KMS("CDCLK running at %dKHz\n",
- dev_priv->display.get_display_clock_speed(dev));
+ cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
+ DRM_DEBUG_KMS("CDCLK running at %dKHz\n", cdclk_freq);
if (IS_SKYLAKE(dev)) {
+ dev_priv->skl_boot_cdclk = cdclk_freq;
if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
DRM_ERROR("LCPLL1 is disabled\n");
+ else
+ intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
} else if (IS_BROXTON(dev)) {
broxton_init_cdclk(dev);
broxton_ddi_phy_init(dev);