From 49cd97a35d9041b53ecf39d447f6a0f8f2de75eb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Feb 2017 20:33:45 +0200 Subject: [PATCH] drm/i915: Start moving the cdclk stuff into a distinct state structure MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Introduce intel_cdclk state which for now will track the cdclk frequency, the vco frequency and the reference frequency (not sure we want the last one, but I put it there anyway). We'll also make the .get_cdclk() function fill out this state structure rather than just returning the current cdclk frequency. One immediate benefit is that calling .get_cdclk() will no longer clobber state stored under dev_priv unless ex[plicitly told to do so. Previously it clobbered the vco and reference clocks stored there on some platforms. We'll expand the use of this structure to actually precomputing the state and whatnot later. v2: Constify intel_cdclk_state_compare() v3: Document intel_cdclk_state_compare() v4: Deal with i945gm_get_cdclk() Signed-off-by: Ville Syrjälä Reviewed-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/20170207183345.19763-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 14 +- drivers/gpu/drm/i915/intel_audio.c | 2 +- drivers/gpu/drm/i915/intel_cdclk.c | 382 ++++++++++++++---------- drivers/gpu/drm/i915/intel_display.c | 18 +- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 3 + drivers/gpu/drm/i915/intel_fbc.c | 2 +- drivers/gpu/drm/i915/intel_panel.c | 4 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 5 +- 10 files changed, 258 insertions(+), 176 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6400f83d3ad1..1ccc2978a21a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1281,7 +1281,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_puts(m, "no P-state info available\n"); } - seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk_freq); + seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk.hw.cdclk); seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq); seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f41496405484..aa59b2153374 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -600,9 +600,11 @@ struct intel_initial_plane_config; struct intel_crtc; struct intel_limit; struct dpll; +struct intel_cdclk_state; struct drm_i915_display_funcs { - int (*get_cdclk)(struct drm_i915_private *dev_priv); + void (*get_cdclk)(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state); int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane); int (*compute_pipe_wm)(struct intel_crtc_state *cstate); int (*compute_intermediate_wm)(struct drm_device *dev, @@ -2060,6 +2062,10 @@ struct i915_oa_ops { bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv); }; +struct intel_cdclk_state { + unsigned int cdclk, vco, ref; +}; + struct drm_i915_private { struct drm_device drm; @@ -2164,7 +2170,7 @@ struct drm_i915_private { unsigned int fsb_freq, mem_freq, is_ddr3; unsigned int skl_preferred_vco_freq; - unsigned int cdclk_freq, max_cdclk_freq; + unsigned int max_cdclk_freq; /* * For reading holding any crtc lock is sufficient, @@ -2178,8 +2184,8 @@ struct drm_i915_private { unsigned int czclk_freq; struct { - unsigned int vco, ref; - } cdclk_pll; + struct intel_cdclk_state hw; + } cdclk; /** * wq - Driver workqueue for GEM. diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index cd9d20763140..1ab401faed34 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -734,7 +734,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) if (WARN_ON_ONCE(!HAS_DDI(dev_priv))) return -ENODEV; - return dev_priv->cdclk_freq; + return dev_priv->cdclk.hw.cdclk; } /* diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index a0736b5f2d47..4e74e87a8676 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -51,37 +51,44 @@ * dividers can be programmed correctly. */ -static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv) +static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { - return 133333; + cdclk_state->cdclk = 133333; } -static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv) +static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { - return 200000; + cdclk_state->cdclk = 200000; } -static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv) +static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { - return 266667; + cdclk_state->cdclk = 266667; } -static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv) +static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { - return 333333; + cdclk_state->cdclk = 333333; } -static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv) +static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { - return 400000; + cdclk_state->cdclk = 400000; } -static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv) +static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { - return 450000; + cdclk_state->cdclk = 450000; } -static int i85x_get_cdclk(struct drm_i915_private *dev_priv) +static void i85x_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { struct pci_dev *pdev = dev_priv->drm.pdev; u16 hpllcc = 0; @@ -91,8 +98,10 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv) * encoding is different :( * FIXME is this the right way to detect 852GM/852GMV? */ - if (pdev->revision == 0x1) - return 133333; + if (pdev->revision == 0x1) { + cdclk_state->cdclk = 133333; + return; + } pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 3), HPLLCC, &hpllcc); @@ -104,56 +113,67 @@ static int i85x_get_cdclk(struct drm_i915_private *dev_priv) case GC_CLOCK_133_200: case GC_CLOCK_133_200_2: case GC_CLOCK_100_200: - return 200000; + cdclk_state->cdclk = 200000; + break; case GC_CLOCK_166_250: - return 250000; + cdclk_state->cdclk = 250000; + break; case GC_CLOCK_100_133: - return 133333; + cdclk_state->cdclk = 133333; + break; case GC_CLOCK_133_266: case GC_CLOCK_133_266_2: case GC_CLOCK_166_266: - return 266667; + cdclk_state->cdclk = 266667; + break; } - - /* Shouldn't happen */ - return 0; } -static int i915gm_get_cdclk(struct drm_i915_private *dev_priv) +static void i915gm_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { struct pci_dev *pdev = dev_priv->drm.pdev; u16 gcfgc = 0; pci_read_config_word(pdev, GCFGC, &gcfgc); - if (gcfgc & GC_LOW_FREQUENCY_ENABLE) - return 133333; + if (gcfgc & GC_LOW_FREQUENCY_ENABLE) { + cdclk_state->cdclk = 133333; + return; + } switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_333_320_MHZ: - return 333333; + cdclk_state->cdclk = 333333; + break; default: case GC_DISPLAY_CLOCK_190_200_MHZ: - return 190000; + cdclk_state->cdclk = 190000; + break; } } -static int i945gm_get_cdclk(struct drm_i915_private *dev_priv) +static void i945gm_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { struct pci_dev *pdev = dev_priv->drm.pdev; u16 gcfgc = 0; pci_read_config_word(pdev, GCFGC, &gcfgc); - if (gcfgc & GC_LOW_FREQUENCY_ENABLE) - return 133333; + if (gcfgc & GC_LOW_FREQUENCY_ENABLE) { + cdclk_state->cdclk = 133333; + return; + } switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_333_320_MHZ: - return 320000; + cdclk_state->cdclk = 320000; + break; default: case GC_DISPLAY_CLOCK_190_200_MHZ: - return 200000; + cdclk_state->cdclk = 200000; + break; } } @@ -225,7 +245,8 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv) return vco; } -static int g33_get_cdclk(struct drm_i915_private *dev_priv) +static void g33_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { struct pci_dev *pdev = dev_priv->drm.pdev; static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 }; @@ -233,9 +254,11 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv) static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 }; static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 }; const uint8_t *div_table; - unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); + unsigned int cdclk_sel; uint16_t tmp = 0; + cdclk_state->vco = intel_hpll_vco(dev_priv); + pci_read_config_word(pdev, GCFGC, &tmp); cdclk_sel = (tmp >> 4) & 0x7; @@ -243,7 +266,7 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv) if (cdclk_sel >= ARRAY_SIZE(div_3200)) goto fail; - switch (vco) { + switch (cdclk_state->vco) { case 3200000: div_table = div_3200; break; @@ -260,15 +283,18 @@ static int g33_get_cdclk(struct drm_i915_private *dev_priv) goto fail; } - return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]); + cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, + div_table[cdclk_sel]); + return; fail: DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n", - vco, tmp); - return 190476; + cdclk_state->vco, tmp); + cdclk_state->cdclk = 190476; } -static int pnv_get_cdclk(struct drm_i915_private *dev_priv) +static void pnv_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { struct pci_dev *pdev = dev_priv->drm.pdev; u16 gcfgc = 0; @@ -277,32 +303,41 @@ static int pnv_get_cdclk(struct drm_i915_private *dev_priv) switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_267_MHZ_PNV: - return 266667; + cdclk_state->cdclk = 266667; + break; case GC_DISPLAY_CLOCK_333_MHZ_PNV: - return 333333; + cdclk_state->cdclk = 333333; + break; case GC_DISPLAY_CLOCK_444_MHZ_PNV: - return 444444; + cdclk_state->cdclk = 444444; + break; case GC_DISPLAY_CLOCK_200_MHZ_PNV: - return 200000; + cdclk_state->cdclk = 200000; + break; default: DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc); case GC_DISPLAY_CLOCK_133_MHZ_PNV: - return 133333; + cdclk_state->cdclk = 133333; + break; case GC_DISPLAY_CLOCK_167_MHZ_PNV: - return 166667; + cdclk_state->cdclk = 166667; + break; } } -static int i965gm_get_cdclk(struct drm_i915_private *dev_priv) +static void i965gm_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { struct pci_dev *pdev = dev_priv->drm.pdev; static const uint8_t div_3200[] = { 16, 10, 8 }; static const uint8_t div_4000[] = { 20, 12, 10 }; static const uint8_t div_5333[] = { 24, 16, 14 }; const uint8_t *div_table; - unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); + unsigned int cdclk_sel; uint16_t tmp = 0; + cdclk_state->vco = intel_hpll_vco(dev_priv); + pci_read_config_word(pdev, GCFGC, &tmp); cdclk_sel = ((tmp >> 8) & 0x1f) - 1; @@ -310,7 +345,7 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv) if (cdclk_sel >= ARRAY_SIZE(div_3200)) goto fail; - switch (vco) { + switch (cdclk_state->vco) { case 3200000: div_table = div_3200; break; @@ -324,53 +359,62 @@ static int i965gm_get_cdclk(struct drm_i915_private *dev_priv) goto fail; } - return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]); + cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, + div_table[cdclk_sel]); + return; fail: DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n", - vco, tmp); - return 200000; + cdclk_state->vco, tmp); + cdclk_state->cdclk = 200000; } -static int gm45_get_cdclk(struct drm_i915_private *dev_priv) +static void gm45_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { struct pci_dev *pdev = dev_priv->drm.pdev; - unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv); + unsigned int cdclk_sel; uint16_t tmp = 0; + cdclk_state->vco = intel_hpll_vco(dev_priv); + pci_read_config_word(pdev, GCFGC, &tmp); cdclk_sel = (tmp >> 12) & 0x1; - switch (vco) { + switch (cdclk_state->vco) { case 2666667: case 4000000: case 5333333: - return cdclk_sel ? 333333 : 222222; + cdclk_state->cdclk = cdclk_sel ? 333333 : 222222; + break; case 3200000: - return cdclk_sel ? 320000 : 228571; + cdclk_state->cdclk = cdclk_sel ? 320000 : 228571; + break; default: DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n", - vco, tmp); - return 222222; + cdclk_state->vco, tmp); + cdclk_state->cdclk = 222222; + break; } } -static int hsw_get_cdclk(struct drm_i915_private *dev_priv) +static void hsw_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { uint32_t lcpll = I915_READ(LCPLL_CTL); uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; if (lcpll & LCPLL_CD_SOURCE_FCLK) - return 800000; + cdclk_state->cdclk = 800000; else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) - return 450000; + cdclk_state->cdclk = 450000; else if (freq == LCPLL_CLK_FREQ_450) - return 450000; + cdclk_state->cdclk = 450000; else if (IS_HSW_ULT(dev_priv)) - return 337500; + cdclk_state->cdclk = 337500; else - return 540000; + cdclk_state->cdclk = 540000; } static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, @@ -396,10 +440,13 @@ static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, return 200000; } -static int vlv_get_cdclk(struct drm_i915_private *dev_priv) +static void vlv_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { - return vlv_get_cck_clock_hpll(dev_priv, "cdclk", - CCK_DISPLAY_CLOCK_CONTROL); + cdclk_state->vco = vlv_get_hpll_vco(dev_priv); + cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk", + CCK_DISPLAY_CLOCK_CONTROL, + cdclk_state->vco); } static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) @@ -411,7 +458,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) else default_credits = PFI_CREDIT(8); - if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) { + if (dev_priv->cdclk.hw.cdclk >= dev_priv->czclk_freq) { /* CHV suggested value is 31 or 63 */ if (IS_CHERRYVIEW(dev_priv)) credits = PFI_CREDIT_63; @@ -443,8 +490,6 @@ static void vlv_set_cdclk(struct drm_device *dev, int cdclk) struct drm_i915_private *dev_priv = to_i915(dev); u32 val, cmd; - WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq); - if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ cmd = 2; else if (cdclk == 266667) @@ -508,8 +553,6 @@ static void chv_set_cdclk(struct drm_device *dev, int cdclk) struct drm_i915_private *dev_priv = to_i915(dev); u32 val, cmd; - WARN_ON(dev_priv->display.get_cdclk(dev_priv) != dev_priv->cdclk_freq); - switch (cdclk) { case 333333: case 320000: @@ -555,23 +598,24 @@ static int bdw_calc_cdclk(int max_pixclk) return 337500; } -static int bdw_get_cdclk(struct drm_i915_private *dev_priv) +static void bdw_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { uint32_t lcpll = I915_READ(LCPLL_CTL); uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; if (lcpll & LCPLL_CD_SOURCE_FCLK) - return 800000; + cdclk_state->cdclk = 800000; else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) - return 450000; + cdclk_state->cdclk = 450000; else if (freq == LCPLL_CLK_FREQ_450) - return 450000; + cdclk_state->cdclk = 450000; else if (freq == LCPLL_CLK_FREQ_54O_BDW) - return 540000; + cdclk_state->cdclk = 540000; else if (freq == LCPLL_CLK_FREQ_337_5_BDW) - return 337500; + cdclk_state->cdclk = 337500; else - return 675000; + cdclk_state->cdclk = 675000; } static void bdw_set_cdclk(struct drm_device *dev, int cdclk) @@ -648,9 +692,9 @@ static void bdw_set_cdclk(struct drm_device *dev, int cdclk) intel_update_cdclk(dev_priv); - WARN(cdclk != dev_priv->cdclk_freq, + WARN(cdclk != dev_priv->cdclk.hw.cdclk, "cdclk requested %d kHz but got %d kHz\n", - cdclk, dev_priv->cdclk_freq); + cdclk, dev_priv->cdclk.hw.cdclk); } static int skl_calc_cdclk(int max_pixclk, int vco) @@ -676,12 +720,13 @@ static int skl_calc_cdclk(int max_pixclk, int vco) } } -static void skl_dpll0_update(struct drm_i915_private *dev_priv) +static void skl_dpll0_update(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { u32 val; - dev_priv->cdclk_pll.ref = 24000; - dev_priv->cdclk_pll.vco = 0; + cdclk_state->ref = 24000; + cdclk_state->vco = 0; val = I915_READ(LCPLL1_CTL); if ((val & LCPLL_PLL_ENABLE) == 0) @@ -703,11 +748,11 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv) case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0): - dev_priv->cdclk_pll.vco = 8100000; + cdclk_state->vco = 8100000; break; case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0): case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0): - dev_priv->cdclk_pll.vco = 8640000; + cdclk_state->vco = 8640000; break; default: MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)); @@ -715,46 +760,57 @@ static void skl_dpll0_update(struct drm_i915_private *dev_priv) } } -static int skl_get_cdclk(struct drm_i915_private *dev_priv) +static void skl_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { u32 cdctl; - skl_dpll0_update(dev_priv); + skl_dpll0_update(dev_priv, cdclk_state); - if (dev_priv->cdclk_pll.vco == 0) - return dev_priv->cdclk_pll.ref; + cdclk_state->cdclk = cdclk_state->ref; + + if (cdclk_state->vco == 0) + return; cdctl = I915_READ(CDCLK_CTL); - if (dev_priv->cdclk_pll.vco == 8640000) { + if (cdclk_state->vco == 8640000) { switch (cdctl & CDCLK_FREQ_SEL_MASK) { case CDCLK_FREQ_450_432: - return 432000; + cdclk_state->cdclk = 432000; + break; case CDCLK_FREQ_337_308: - return 308571; + cdclk_state->cdclk = 308571; + break; case CDCLK_FREQ_540: - return 540000; + cdclk_state->cdclk = 540000; + break; case CDCLK_FREQ_675_617: - return 617143; + cdclk_state->cdclk = 617143; + break; default: MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK); + break; } } else { switch (cdctl & CDCLK_FREQ_SEL_MASK) { case CDCLK_FREQ_450_432: - return 450000; + cdclk_state->cdclk = 450000; + break; case CDCLK_FREQ_337_308: - return 337500; + cdclk_state->cdclk = 337500; + break; case CDCLK_FREQ_540: - return 540000; + cdclk_state->cdclk = 540000; + break; case CDCLK_FREQ_675_617: - return 675000; + cdclk_state->cdclk = 675000; + break; default: MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK); + break; } } - - return dev_priv->cdclk_pll.ref; } /* convert from kHz to .1 fixpoint MHz with -1MHz offset */ @@ -817,7 +873,7 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco) 5)) DRM_ERROR("DPLL0 not locked\n"); - dev_priv->cdclk_pll.vco = vco; + dev_priv->cdclk.hw.vco = vco; /* We'll want to keep using the current vco from now on. */ skl_set_preferred_cdclk_vco(dev_priv, vco); @@ -831,7 +887,7 @@ static void skl_dpll0_disable(struct drm_i915_private *dev_priv) 1)) DRM_ERROR("Couldn't disable DPLL0\n"); - dev_priv->cdclk_pll.vco = 0; + dev_priv->cdclk.hw.vco = 0; } static void skl_set_cdclk(struct drm_i915_private *dev_priv, @@ -881,11 +937,11 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, break; } - if (dev_priv->cdclk_pll.vco != 0 && - dev_priv->cdclk_pll.vco != vco) + if (dev_priv->cdclk.hw.vco != 0 && + dev_priv->cdclk.hw.vco != vco) skl_dpll0_disable(dev_priv); - if (dev_priv->cdclk_pll.vco != vco) + if (dev_priv->cdclk.hw.vco != vco) skl_dpll0_enable(dev_priv, vco); I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk)); @@ -913,8 +969,8 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv) intel_update_cdclk(dev_priv); /* Is PLL enabled and locked ? */ - if (dev_priv->cdclk_pll.vco == 0 || - dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref) + if (dev_priv->cdclk.hw.vco == 0 || + dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref) goto sanitize; /* DPLL okay; verify the cdclock @@ -925,7 +981,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv) */ cdctl = I915_READ(CDCLK_CTL); expected = (cdctl & CDCLK_FREQ_SEL_MASK) | - skl_cdclk_decimal(dev_priv->cdclk_freq); + skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk); if (cdctl == expected) /* All well; nothing to sanitize */ return; @@ -934,9 +990,9 @@ sanitize: DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n"); /* force cdclk programming */ - dev_priv->cdclk_freq = 0; + dev_priv->cdclk.hw.cdclk = 0; /* force full PLL disable + enable */ - dev_priv->cdclk_pll.vco = -1; + dev_priv->cdclk.hw.vco = -1; } /** @@ -954,14 +1010,15 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) skl_sanitize_cdclk(dev_priv); - if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) { + if (dev_priv->cdclk.hw.cdclk != 0 && + dev_priv->cdclk.hw.vco != 0) { /* * Use the current vco as our initial * guess as to what the preferred vco is. */ if (dev_priv->skl_preferred_vco_freq == 0) skl_set_preferred_cdclk_vco(dev_priv, - dev_priv->cdclk_pll.vco); + dev_priv->cdclk.hw.vco); return; } @@ -982,7 +1039,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) */ void skl_uninit_cdclk(struct drm_i915_private *dev_priv) { - skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0); + skl_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0); } static int bxt_calc_cdclk(int max_pixclk) @@ -1013,7 +1070,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) { int ratio; - if (cdclk == dev_priv->cdclk_pll.ref) + if (cdclk == dev_priv->cdclk.hw.ref) return 0; switch (cdclk) { @@ -1030,14 +1087,14 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) break; } - return dev_priv->cdclk_pll.ref * ratio; + return dev_priv->cdclk.hw.ref * ratio; } static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) { int ratio; - if (cdclk == dev_priv->cdclk_pll.ref) + if (cdclk == dev_priv->cdclk.hw.ref) return 0; switch (cdclk) { @@ -1050,15 +1107,16 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk) break; } - return dev_priv->cdclk_pll.ref * ratio; + return dev_priv->cdclk.hw.ref * ratio; } -static void bxt_de_pll_update(struct drm_i915_private *dev_priv) +static void bxt_de_pll_update(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { u32 val; - dev_priv->cdclk_pll.ref = 19200; - dev_priv->cdclk_pll.vco = 0; + cdclk_state->ref = 19200; + cdclk_state->vco = 0; val = I915_READ(BXT_DE_PLL_ENABLE); if ((val & BXT_DE_PLL_PLL_ENABLE) == 0) @@ -1068,20 +1126,21 @@ static void bxt_de_pll_update(struct drm_i915_private *dev_priv) return; val = I915_READ(BXT_DE_PLL_CTL); - dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) * - dev_priv->cdclk_pll.ref; + cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref; } -static int bxt_get_cdclk(struct drm_i915_private *dev_priv) +static void bxt_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) { u32 divider; - int div, vco; + int div; - bxt_de_pll_update(dev_priv); + bxt_de_pll_update(dev_priv, cdclk_state); - vco = dev_priv->cdclk_pll.vco; - if (vco == 0) - return dev_priv->cdclk_pll.ref; + cdclk_state->cdclk = cdclk_state->ref; + + if (cdclk_state->vco == 0) + return; divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK; @@ -1101,10 +1160,10 @@ static int bxt_get_cdclk(struct drm_i915_private *dev_priv) break; default: MISSING_CASE(divider); - return dev_priv->cdclk_pll.ref; + return; } - return DIV_ROUND_CLOSEST(vco, div); + cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div); } static void bxt_de_pll_disable(struct drm_i915_private *dev_priv) @@ -1117,12 +1176,12 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv) 1)) DRM_ERROR("timeout waiting for DE PLL unlock\n"); - dev_priv->cdclk_pll.vco = 0; + dev_priv->cdclk.hw.vco = 0; } static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco) { - int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref); + int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref); u32 val; val = I915_READ(BXT_DE_PLL_CTL); @@ -1140,7 +1199,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco) 1)) DRM_ERROR("timeout waiting for DE PLL lock\n"); - dev_priv->cdclk_pll.vco = vco; + dev_priv->cdclk.hw.vco = vco; } static void bxt_set_cdclk(struct drm_i915_private *dev_priv, @@ -1168,7 +1227,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, divider = BXT_CDCLK_CD2X_DIV_SEL_1; break; default: - WARN_ON(cdclk != dev_priv->cdclk_pll.ref); + WARN_ON(cdclk != dev_priv->cdclk.hw.ref); WARN_ON(vco != 0); divider = BXT_CDCLK_CD2X_DIV_SEL_1; @@ -1187,11 +1246,11 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, return; } - if (dev_priv->cdclk_pll.vco != 0 && - dev_priv->cdclk_pll.vco != vco) + if (dev_priv->cdclk.hw.vco != 0 && + dev_priv->cdclk.hw.vco != vco) bxt_de_pll_disable(dev_priv); - if (dev_priv->cdclk_pll.vco != vco) + if (dev_priv->cdclk.hw.vco != vco) bxt_de_pll_enable(dev_priv, vco); val = divider | skl_cdclk_decimal(cdclk); @@ -1228,8 +1287,8 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) intel_update_cdclk(dev_priv); - if (dev_priv->cdclk_pll.vco == 0 || - dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref) + if (dev_priv->cdclk.hw.vco == 0 || + dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref) goto sanitize; /* DPLL okay; verify the cdclock @@ -1247,12 +1306,12 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv) cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE; expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) | - skl_cdclk_decimal(dev_priv->cdclk_freq); + skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk); /* * Disable SSA Precharge when CD clock frequency < 500 MHz, * enable otherwise. */ - if (dev_priv->cdclk_freq >= 500000) + if (dev_priv->cdclk.hw.cdclk >= 500000) expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE; if (cdctl == expected) @@ -1263,10 +1322,10 @@ sanitize: DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n"); /* force cdclk programming */ - dev_priv->cdclk_freq = 0; + dev_priv->cdclk.hw.cdclk = 0; /* force full PLL disable + enable */ - dev_priv->cdclk_pll.vco = -1; + dev_priv->cdclk.hw.vco = -1; } /** @@ -1284,7 +1343,8 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv) bxt_sanitize_cdclk(dev_priv); - if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) + if (dev_priv->cdclk.hw.cdclk != 0 && + dev_priv->cdclk.hw.vco != 0) return; /* @@ -1312,7 +1372,21 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv) */ void bxt_uninit_cdclk(struct drm_i915_private *dev_priv) { - bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0); + bxt_set_cdclk(dev_priv, dev_priv->cdclk.hw.ref, 0); +} + +/** + * intel_cdclk_state_compare - Determine if two CDCLK states differ + * @a: first CDCLK state + * @b: second CDCLK state + * + * Returns: + * True if the CDCLK states are identical, false if they differ. + */ +bool intel_cdclk_state_compare(const struct intel_cdclk_state *a, + const struct intel_cdclk_state *b) +{ + return memcmp(a, b, sizeof(*a)) == 0; } static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state, @@ -1620,7 +1694,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) dev_priv->max_cdclk_freq = 400000; } else { /* otherwise assume cdclk is fixed */ - dev_priv->max_cdclk_freq = dev_priv->cdclk_freq; + dev_priv->max_cdclk_freq = dev_priv->cdclk.hw.cdclk; } dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv); @@ -1640,15 +1714,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) */ void intel_update_cdclk(struct drm_i915_private *dev_priv) { - dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv); + dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw); - if (INTEL_GEN(dev_priv) >= 9) - DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n", - dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco, - dev_priv->cdclk_pll.ref); - else - DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n", - dev_priv->cdclk_freq); + DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n", + dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco, + dev_priv->cdclk.hw.ref); /* * 9:0 CMBUS [sic] CDCLK frequency (cdfreq): @@ -1658,7 +1728,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv) */ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) I915_WRITE(GMBUSFREQ_VLV, - DIV_ROUND_UP(dev_priv->cdclk_freq, 1000)); + DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000)); } static int pch_rawclk(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e996f8ec8f08..691db36d8388 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -135,7 +135,7 @@ struct intel_limit { }; /* returns HPLL frequency in kHz */ -static int valleyview_get_vco(struct drm_i915_private *dev_priv) +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv) { int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; @@ -171,7 +171,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, const char *name, u32 reg) { if (dev_priv->hpll_freq == 0) - dev_priv->hpll_freq = valleyview_get_vco(dev_priv); + dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv); return vlv_get_cck_clock(dev_priv, name, reg, dev_priv->hpll_freq); @@ -12413,7 +12413,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) */ if (dev_priv->display.modeset_calc_cdclk) { if (!intel_state->cdclk_pll_vco) - intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco; + intel_state->cdclk_pll_vco = dev_priv->cdclk.hw.vco; if (!intel_state->cdclk_pll_vco) intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq; @@ -12433,8 +12433,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state) } /* All pipes must be switched off while we change the cdclk. */ - if (intel_state->dev_cdclk != dev_priv->cdclk_freq || - intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) { + if (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk || + intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco) { ret = intel_modeset_all_pipes(state); if (ret < 0) return ret; @@ -12869,8 +12869,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_update_legacy_modeset_state(state->dev, state); if (dev_priv->display.modeset_commit_cdclk && - (intel_state->dev_cdclk != dev_priv->cdclk_freq || - intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco)) + (intel_state->dev_cdclk != dev_priv->cdclk.hw.cdclk || + intel_state->cdclk_pll_vco != dev_priv->cdclk.hw.vco)) dev_priv->display.modeset_commit_cdclk(state); /* @@ -14855,7 +14855,7 @@ void intel_modeset_init_hw(struct drm_device *dev) intel_update_cdclk(dev_priv); - dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; + dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk; intel_init_clock_gating(dev_priv); } @@ -15031,7 +15031,7 @@ int intel_modeset_init(struct drm_device *dev) intel_update_czclk(dev_priv); intel_update_cdclk(dev_priv); - dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; + dev_priv->atomic_cdclk_freq = dev_priv->cdclk.hw.cdclk; intel_shared_dpll_init(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 21924cf4c8ad..f8c23fed4a2c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -918,7 +918,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) * divide by 2000 and use that */ if (intel_dig_port->port == PORT_A) - return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000); + return DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.cdclk, 2000); else return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4bdb1f3cb0b5..ba0728ccff75 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1251,10 +1251,13 @@ 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_cdclk(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, + const struct intel_cdclk_state *b); /* intel_display.c */ enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc); void intel_update_rawclk(struct drm_i915_private *dev_priv); +int vlv_get_hpll_vco(struct drm_i915_private *dev_priv); int vlv_get_cck_clock(struct drm_i915_private *dev_priv, const char *name, u32 reg, int ref_freq); int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index c66ba7e36289..22c56ae086f2 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -817,7 +817,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) /* WaFbcExceedCdClockThreshold:hsw,bdw */ if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && - cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) { + cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) { fbc->no_fbc_reason = "pixel rate is too big"; return false; } diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 1a6ff26dea20..cb50c527401f 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1315,7 +1315,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) if (IS_PINEVIEW(dev_priv)) clock = KHz(dev_priv->rawclk_freq); else - clock = KHz(dev_priv->cdclk_freq); + clock = KHz(dev_priv->cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32); } @@ -1333,7 +1333,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) if (IS_G4X(dev_priv)) clock = KHz(dev_priv->rawclk_freq); else - clock = KHz(dev_priv->cdclk_freq); + clock = KHz(dev_priv->cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 915914f9444c..0f00a5aab69c 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -964,9 +964,12 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv) static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { + struct intel_cdclk_state cdclk_state = {}; + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); - WARN_ON(dev_priv->cdclk_freq != dev_priv->display.get_cdclk(dev_priv)); + dev_priv->display.get_cdclk(dev_priv, &cdclk_state); + WARN_ON(!intel_cdclk_state_compare(&dev_priv->cdclk.hw, &cdclk_state)); gen9_assert_dbuf_enabled(dev_priv); -- 2.20.1