[Intel-gfx] [PATCH 05/14] drm/i915: Move most cdclk/rawclk related code to intel_cdclk.c
Ander Conselvan De Oliveira
conselvan2 at gmail.com
Thu Dec 22 13:10:16 UTC 2016
On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
> Let's try to shrink intel_display.c a bit by moving the cdclk/rawclk
> stuff to a new file. It's all reasonably self contained so we don't
> even have to add that many non-static symbols.
>
> We'll also take the opportunity to shuffle around the functions a bit
> to get things in a more consistent order based on the platform.
Hmm, maybe this is the moment to add some kerneldoc to this stuff, or Daniel
might be grumpy? :)
The new file makes sense, didn't really check the move line by line, but
Reviewed-by: Ander Conselvan de Oliveira <conselvan2 at gmail.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
> drivers/gpu/drm/i915/Makefile | 1 +
> drivers/gpu/drm/i915/intel_cdclk.c | 1690 +++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_display.c | 2115 ++++-----------------------------
> -
> drivers/gpu/drm/i915/intel_drv.h | 9 +-
> 4 files changed, 1922 insertions(+), 1893 deletions(-)
> create mode 100644 drivers/gpu/drm/i915/intel_cdclk.c
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 5196509e71cf..3f5c21b76e85 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -70,6 +70,7 @@ i915-y += intel_audio.o \
> intel_atomic.o \
> intel_atomic_plane.o \
> intel_bios.o \
> + intel_cdclk.o \
> intel_color.o \
> intel_display.o \
> intel_dpio_phy.o \
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c
> b/drivers/gpu/drm/i915/intel_cdclk.c
> new file mode 100644
> index 000000000000..1804c43553b7
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -0,0 +1,1690 @@
> +/*
> + * Copyright © 2006-2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include "intel_drv.h"
> +
> +static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + return 133333;
> +}
> +
> +static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + return 200000;
> +}
> +
> +static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + return 266667;
> +}
> +
> +static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + return 333333;
> +}
> +
> +static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + return 400000;
> +}
> +
> +static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + return 450000;
> +}
> +
> +static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + struct pci_dev *pdev = dev_priv->drm.pdev;
> + u16 hpllcc = 0;
> +
> + /*
> + * 852GM/852GMV only supports 133 MHz and the HPLLCC
> + * encoding is different :(
> + * FIXME is this the right way to detect 852GM/852GMV?
> + */
> + if (pdev->revision == 0x1)
> + return 133333;
> +
> + pci_bus_read_config_word(pdev->bus,
> + PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
> +
> + /* Assume that the hardware is in the high speed state. This
> + * should be the default.
> + */
> + switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
> + case GC_CLOCK_133_200:
> + case GC_CLOCK_133_200_2:
> + case GC_CLOCK_100_200:
> + return 200000;
> + case GC_CLOCK_166_250:
> + return 250000;
> + case GC_CLOCK_100_133:
> + return 133333;
> + case GC_CLOCK_133_266:
> + case GC_CLOCK_133_266_2:
> + case GC_CLOCK_166_266:
> + return 266667;
> + }
> +
> + /* Shouldn't happen */
> + return 0;
> +}
> +
> +static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + 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;
> +
> + switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> + case GC_DISPLAY_CLOCK_333_MHZ:
> + return 333333;
> + default:
> + case GC_DISPLAY_CLOCK_190_200_MHZ:
> + return 190000;
> + }
> +}
> +
> +static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
> +{
> + static const unsigned int blb_vco[8] = {
> + [0] = 3200000,
> + [1] = 4000000,
> + [2] = 5333333,
> + [3] = 4800000,
> + [4] = 6400000,
> + };
> + static const unsigned int pnv_vco[8] = {
> + [0] = 3200000,
> + [1] = 4000000,
> + [2] = 5333333,
> + [3] = 4800000,
> + [4] = 2666667,
> + };
> + static const unsigned int cl_vco[8] = {
> + [0] = 3200000,
> + [1] = 4000000,
> + [2] = 5333333,
> + [3] = 6400000,
> + [4] = 3333333,
> + [5] = 3566667,
> + [6] = 4266667,
> + };
> + static const unsigned int elk_vco[8] = {
> + [0] = 3200000,
> + [1] = 4000000,
> + [2] = 5333333,
> + [3] = 4800000,
> + };
> + static const unsigned int ctg_vco[8] = {
> + [0] = 3200000,
> + [1] = 4000000,
> + [2] = 5333333,
> + [3] = 6400000,
> + [4] = 2666667,
> + [5] = 4266667,
> + };
> + const unsigned int *vco_table;
> + unsigned int vco;
> + uint8_t tmp = 0;
> +
> + /* FIXME other chipsets? */
> + if (IS_GM45(dev_priv))
> + vco_table = ctg_vco;
> + else if (IS_G4X(dev_priv))
> + vco_table = elk_vco;
> + else if (IS_I965GM(dev_priv))
> + vco_table = cl_vco;
> + else if (IS_PINEVIEW(dev_priv))
> + vco_table = pnv_vco;
> + else if (IS_G33(dev_priv))
> + vco_table = blb_vco;
> + else
> + return 0;
> +
> + tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
> +
> + vco = vco_table[tmp & 0x7];
> + if (vco == 0)
> + DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
> + else
> + DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
> +
> + return vco;
> +}
> +
> +static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + struct pci_dev *pdev = dev_priv->drm.pdev;
> + static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 };
> + static const uint8_t div_4000[] = { 14, 12, 10, 8, 6, 20 };
> + 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);
> + uint16_t tmp = 0;
> +
> + pci_read_config_word(pdev, GCFGC, &tmp);
> +
> + cdclk_sel = (tmp >> 4) & 0x7;
> +
> + if (cdclk_sel >= ARRAY_SIZE(div_3200))
> + goto fail;
> +
> + switch (vco) {
> + case 3200000:
> + div_table = div_3200;
> + break;
> + case 4000000:
> + div_table = div_4000;
> + break;
> + case 4800000:
> + div_table = div_4800;
> + break;
> + case 5333333:
> + div_table = div_5333;
> + break;
> + default:
> + goto fail;
> + }
> +
> + return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> +
> +fail:
> + DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%08x\n",
> + vco, tmp);
> + return 190476;
> +}
> +
> +static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + struct pci_dev *pdev = dev_priv->drm.pdev;
> + u16 gcfgc = 0;
> +
> + pci_read_config_word(pdev, GCFGC, &gcfgc);
> +
> + switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> + case GC_DISPLAY_CLOCK_267_MHZ_PNV:
> + return 266667;
> + case GC_DISPLAY_CLOCK_333_MHZ_PNV:
> + return 333333;
> + case GC_DISPLAY_CLOCK_444_MHZ_PNV:
> + return 444444;
> + case GC_DISPLAY_CLOCK_200_MHZ_PNV:
> + return 200000;
> + default:
> + DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
> + case GC_DISPLAY_CLOCK_133_MHZ_PNV:
> + return 133333;
> + case GC_DISPLAY_CLOCK_167_MHZ_PNV:
> + return 166667;
> + }
> +}
> +
> +static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + 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);
> + uint16_t tmp = 0;
> +
> + pci_read_config_word(pdev, GCFGC, &tmp);
> +
> + cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
> +
> + if (cdclk_sel >= ARRAY_SIZE(div_3200))
> + goto fail;
> +
> + switch (vco) {
> + case 3200000:
> + div_table = div_3200;
> + break;
> + case 4000000:
> + div_table = div_4000;
> + break;
> + case 5333333:
> + div_table = div_5333;
> + break;
> + default:
> + goto fail;
> + }
> +
> + return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> +
> +fail:
> + DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%04x\n",
> + vco, tmp);
> + return 200000;
> +}
> +
> +static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + struct pci_dev *pdev = dev_priv->drm.pdev;
> + unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> + uint16_t tmp = 0;
> +
> + pci_read_config_word(pdev, GCFGC, &tmp);
> +
> + cdclk_sel = (tmp >> 12) & 0x1;
> +
> + switch (vco) {
> + case 2666667:
> + case 4000000:
> + case 5333333:
> + return cdclk_sel ? 333333 : 222222;
> + case 3200000:
> + return cdclk_sel ? 320000 : 228571;
> + default:
> + DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u,
> CFGC=0x%04x\n",
> + vco, tmp);
> + return 222222;
> + }
> +}
> +
> +static int hsw_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + uint32_t lcpll = I915_READ(LCPLL_CTL);
> + uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> +
> + if (lcpll & LCPLL_CD_SOURCE_FCLK)
> + return 800000;
> + else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> + return 450000;
> + else if (freq == LCPLL_CLK_FREQ_450)
> + return 450000;
> + else if (IS_HSW_ULT(dev_priv))
> + return 337500;
> + else
> + return 540000;
> +}
> +
> +static int vlv_calc_cdclk(struct drm_i915_private *dev_priv,
> + int max_pixclk)
> +{
> + int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ?
> + 333333 : 320000;
> + int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
> +
> + /*
> + * We seem to get an unstable or solid color picture at 200MHz.
> + * Not sure what's wrong. For now use 200MHz only when all pipes
> + * are off.
> + */
> + if (!IS_CHERRYVIEW(dev_priv) &&
> + max_pixclk > freq_320*limit/100)
> + return 400000;
> + else if (max_pixclk > 266667*limit/100)
> + return freq_320;
> + else if (max_pixclk > 0)
> + return 266667;
> + else
> + return 200000;
> +}
> +
> +static int vlv_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
> + CCK_DISPLAY_CLOCK_CONTROL);
> +}
> +
> +static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
> +{
> + unsigned int credits, default_credits;
> +
> + if (IS_CHERRYVIEW(dev_priv))
> + default_credits = PFI_CREDIT(12);
> + else
> + default_credits = PFI_CREDIT(8);
> +
> + if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
> + /* CHV suggested value is 31 or 63 */
> + if (IS_CHERRYVIEW(dev_priv))
> + credits = PFI_CREDIT_63;
> + else
> + credits = PFI_CREDIT(15);
> + } else {
> + credits = default_credits;
> + }
> +
> + /*
> + * WA - write default credits before re-programming
> + * FIXME: should we also set the resend bit here?
> + */
> + I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> + default_credits);
> +
> + I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> + credits | PFI_CREDIT_RESEND);
> +
> + /*
> + * FIXME is this guaranteed to clear
> + * immediately or should we poll for it?
> + */
> + WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
> +}
> +
> +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)
> + cmd = 1;
> + else
> + cmd = 0;
> +
> + mutex_lock(&dev_priv->rps.hw_lock);
> + val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> + val &= ~DSPFREQGUAR_MASK;
> + val |= (cmd << DSPFREQGUAR_SHIFT);
> + vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> + if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> + DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
> + 50)) {
> + DRM_ERROR("timed out waiting for CDclk change\n");
> + }
> + mutex_unlock(&dev_priv->rps.hw_lock);
> +
> + mutex_lock(&dev_priv->sb_lock);
> +
> + if (cdclk == 400000) {
> + u32 divider;
> +
> + divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1,
> + cdclk) - 1;
> +
> + /* adjust cdclk divider */
> + val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
> + val &= ~CCK_FREQUENCY_VALUES;
> + val |= divider;
> + vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
> +
> + if (wait_for((vlv_cck_read(dev_priv,
> CCK_DISPLAY_CLOCK_CONTROL) &
> + CCK_FREQUENCY_STATUS) == (divider <<
> CCK_FREQUENCY_STATUS_SHIFT),
> + 50))
> + DRM_ERROR("timed out waiting for CDclk change\n");
> + }
> +
> + /* adjust self-refresh exit latency value */
> + val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
> + val &= ~0x7f;
> +
> + /*
> + * For high bandwidth configs, we set a higher latency in the bunit
> + * so that the core display fetch happens in time to avoid underruns.
> + */
> + if (cdclk == 400000)
> + val |= 4500 / 250; /* 4.5 usec */
> + else
> + val |= 3000 / 250; /* 3.0 usec */
> + vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
> +
> + mutex_unlock(&dev_priv->sb_lock);
> +
> + intel_update_cdclk(dev_priv);
> +}
> +
> +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:
> + case 266667:
> + case 200000:
> + break;
> + default:
> + MISSING_CASE(cdclk);
> + return;
> + }
> +
> + /*
> + * Specs are full of misinformation, but testing on actual
> + * hardware has shown that we just need to write the desired
> + * CCK divider into the Punit register.
> + */
> + cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
> +
> + mutex_lock(&dev_priv->rps.hw_lock);
> + val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> + val &= ~DSPFREQGUAR_MASK_CHV;
> + val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
> + vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> + if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> + DSPFREQSTAT_MASK_CHV) == (cmd <<
> DSPFREQSTAT_SHIFT_CHV),
> + 50)) {
> + DRM_ERROR("timed out waiting for CDclk change\n");
> + }
> + mutex_unlock(&dev_priv->rps.hw_lock);
> +
> + intel_update_cdclk(dev_priv);
> +}
> +
> +static int bdw_calc_cdclk(int max_pixclk)
> +{
> + if (max_pixclk > 540000)
> + return 675000;
> + else if (max_pixclk > 450000)
> + return 540000;
> + else if (max_pixclk > 337500)
> + return 450000;
> + else
> + return 337500;
> +}
> +
> +static int bdw_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + uint32_t lcpll = I915_READ(LCPLL_CTL);
> + uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> +
> + if (lcpll & LCPLL_CD_SOURCE_FCLK)
> + return 800000;
> + else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> + return 450000;
> + else if (freq == LCPLL_CLK_FREQ_450)
> + return 450000;
> + else if (freq == LCPLL_CLK_FREQ_54O_BDW)
> + return 540000;
> + else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
> + return 337500;
> + else
> + return 675000;
> +}
> +
> +static void bdw_set_cdclk(struct drm_device *dev, int cdclk)
> +{
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + uint32_t val, data;
> + int ret;
> +
> + 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;
> +
> + mutex_lock(&dev_priv->rps.hw_lock);
> + ret = sandybridge_pcode_write(dev_priv,
> + BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ,
> 0x0);
> + mutex_unlock(&dev_priv->rps.hw_lock);
> + if (ret) {
> + DRM_ERROR("failed to inform pcode about cdclk change\n");
> + return;
> + }
> +
> + val = I915_READ(LCPLL_CTL);
> + val |= LCPLL_CD_SOURCE_FCLK;
> + I915_WRITE(LCPLL_CTL, val);
> +
> + if (wait_for_us(I915_READ(LCPLL_CTL) &
> + LCPLL_CD_SOURCE_FCLK_DONE, 1))
> + DRM_ERROR("Switching to FCLK failed\n");
> +
> + val = I915_READ(LCPLL_CTL);
> + val &= ~LCPLL_CLK_FREQ_MASK;
> +
> + switch (cdclk) {
> + case 450000:
> + val |= LCPLL_CLK_FREQ_450;
> + data = 0;
> + break;
> + case 540000:
> + val |= LCPLL_CLK_FREQ_54O_BDW;
> + data = 1;
> + break;
> + case 337500:
> + val |= LCPLL_CLK_FREQ_337_5_BDW;
> + data = 2;
> + break;
> + case 675000:
> + val |= LCPLL_CLK_FREQ_675_BDW;
> + data = 3;
> + break;
> + default:
> + WARN(1, "invalid cdclk frequency\n");
> + return;
> + }
> +
> + I915_WRITE(LCPLL_CTL, val);
> +
> + val = I915_READ(LCPLL_CTL);
> + val &= ~LCPLL_CD_SOURCE_FCLK;
> + I915_WRITE(LCPLL_CTL, val);
> +
> + if (wait_for_us((I915_READ(LCPLL_CTL) &
> + LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
> + DRM_ERROR("Switching back to LCPLL failed\n");
> +
> + mutex_lock(&dev_priv->rps.hw_lock);
> + sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
> + mutex_unlock(&dev_priv->rps.hw_lock);
> +
> + I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
> +
> + intel_update_cdclk(dev_priv);
> +
> + WARN(cdclk != dev_priv->cdclk_freq,
> + "cdclk requested %d kHz but got %d kHz\n",
> + cdclk, dev_priv->cdclk_freq);
> +}
> +
> +static int skl_calc_cdclk(int max_pixclk, int vco)
> +{
> + if (vco == 8640000) {
> + if (max_pixclk > 540000)
> + return 617143;
> + else if (max_pixclk > 432000)
> + return 540000;
> + else if (max_pixclk > 308571)
> + return 432000;
> + else
> + return 308571;
> + } else {
> + if (max_pixclk > 540000)
> + return 675000;
> + else if (max_pixclk > 450000)
> + return 540000;
> + else if (max_pixclk > 337500)
> + return 450000;
> + else
> + return 337500;
> + }
> +}
> +
> +static void skl_dpll0_update(struct drm_i915_private *dev_priv)
> +{
> + u32 val;
> +
> + dev_priv->cdclk_pll.ref = 24000;
> + dev_priv->cdclk_pll.vco = 0;
> +
> + val = I915_READ(LCPLL1_CTL);
> + if ((val & LCPLL_PLL_ENABLE) == 0)
> + return;
> +
> + if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
> + return;
> +
> + val = I915_READ(DPLL_CTRL1);
> +
> + if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
> + DPLL_CTRL1_SSC(SKL_DPLL0) |
> + DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
> + DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
> + return;
> +
> + switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
> + case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
> + 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;
> + 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;
> + break;
> + default:
> + MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> + break;
> + }
> +}
> +
> +static int skl_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + u32 cdctl;
> +
> + skl_dpll0_update(dev_priv);
> +
> + if (dev_priv->cdclk_pll.vco == 0)
> + return dev_priv->cdclk_pll.ref;
> +
> + cdctl = I915_READ(CDCLK_CTL);
> +
> + if (dev_priv->cdclk_pll.vco == 8640000) {
> + switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> + case CDCLK_FREQ_450_432:
> + return 432000;
> + case CDCLK_FREQ_337_308:
> + return 308571;
> + case CDCLK_FREQ_540:
> + return 540000;
> + case CDCLK_FREQ_675_617:
> + return 617143;
> + default:
> + MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> + }
> + } else {
> + switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> + case CDCLK_FREQ_450_432:
> + return 450000;
> + case CDCLK_FREQ_337_308:
> + return 337500;
> + case CDCLK_FREQ_540:
> + return 540000;
> + case CDCLK_FREQ_675_617:
> + return 675000;
> + default:
> + MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> + }
> + }
> +
> + return dev_priv->cdclk_pll.ref;
> +}
> +
> +/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
> +static int skl_cdclk_decimal(int cdclk)
> +{
> + return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
> +}
> +
> +static void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv,
> + int vco)
> +{
> + bool changed = dev_priv->skl_preferred_vco_freq != vco;
> +
> + dev_priv->skl_preferred_vco_freq = vco;
> +
> + if (changed)
> + intel_update_max_cdclk(dev_priv);
> +}
> +
> +static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
> +{
> + int min_cdclk = skl_calc_cdclk(0, vco);
> + u32 val;
> +
> + WARN_ON(vco != 8100000 && vco != 8640000);
> +
> + /* select the minimum CDCLK before enabling DPLL 0 */
> + val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
> + I915_WRITE(CDCLK_CTL, val);
> + POSTING_READ(CDCLK_CTL);
> +
> + /*
> + * We always enable DPLL0 with the lowest link rate possible, but
> still
> + * taking into account the VCO required to operate the eDP panel at
> the
> + * desired frequency. The usual DP link rates operate with a VCO of
> + * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
> + * The modeset code is responsible for the selection of the exact
> link
> + * rate later on, with the constraint of choosing a frequency that
> + * works with vco.
> + */
> + val = I915_READ(DPLL_CTRL1);
> +
> + val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0)
> |
> + DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> + val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
> + if (vco == 8640000)
> + val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
> + SKL_DPLL0);
> + else
> + val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
> + SKL_DPLL0);
> +
> + I915_WRITE(DPLL_CTRL1, val);
> + POSTING_READ(DPLL_CTRL1);
> +
> + I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
> +
> + if (intel_wait_for_register(dev_priv,
> + LCPLL1_CTL, LCPLL_PLL_LOCK,
> LCPLL_PLL_LOCK,
> + 5))
> + DRM_ERROR("DPLL0 not locked\n");
> +
> + dev_priv->cdclk_pll.vco = vco;
> +
> + /* We'll want to keep using the current vco from now on. */
> + skl_set_preferred_cdclk_vco(dev_priv, vco);
> +}
> +
> +static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
> +{
> + I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
> + if (intel_wait_for_register(dev_priv,
> + LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
> + 1))
> + DRM_ERROR("Couldn't disable DPLL0\n");
> +
> + dev_priv->cdclk_pll.vco = 0;
> +}
> +
> +static void skl_set_cdclk(struct drm_i915_private *dev_priv,
> + int cdclk, int vco)
> +{
> + u32 freq_select, pcu_ack;
> + int ret;
> +
> + WARN_ON((cdclk == 24000) != (vco == 0));
> +
> + DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
> + cdclk, vco);
> +
> + mutex_lock(&dev_priv->rps.hw_lock);
> + ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
> + SKL_CDCLK_PREPARE_FOR_CHANGE,
> + SKL_CDCLK_READY_FOR_CHANGE,
> + SKL_CDCLK_READY_FOR_CHANGE, 3);
> + mutex_unlock(&dev_priv->rps.hw_lock);
> + if (ret) {
> + DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
> + ret);
> + return;
> + }
> +
> + /* set CDCLK_CTL */
> + switch (cdclk) {
> + case 450000:
> + case 432000:
> + freq_select = CDCLK_FREQ_450_432;
> + pcu_ack = 1;
> + break;
> + case 540000:
> + freq_select = CDCLK_FREQ_540;
> + pcu_ack = 2;
> + break;
> + case 308571:
> + case 337500:
> + default:
> + freq_select = CDCLK_FREQ_337_308;
> + pcu_ack = 0;
> + break;
> + case 617143:
> + case 675000:
> + freq_select = CDCLK_FREQ_675_617;
> + pcu_ack = 3;
> + break;
> + }
> +
> + if (dev_priv->cdclk_pll.vco != 0 &&
> + dev_priv->cdclk_pll.vco != vco)
> + skl_dpll0_disable(dev_priv);
> +
> + if (dev_priv->cdclk_pll.vco != vco)
> + skl_dpll0_enable(dev_priv, vco);
> +
> + I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
> + POSTING_READ(CDCLK_CTL);
> +
> + /* inform PCU of the change */
> + mutex_lock(&dev_priv->rps.hw_lock);
> + sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
> + mutex_unlock(&dev_priv->rps.hw_lock);
> +
> + intel_update_cdclk(dev_priv);
> +}
> +
> +static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> +{
> + uint32_t cdctl, expected;
> +
> + /*
> + * check if the pre-os initialized the display
> + * There is SWF18 scratchpad register defined which is set by the
> + * pre-os which can be used by the OS drivers to check the status
> + */
> + if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
> + goto sanitize;
> +
> + 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)
> + goto sanitize;
> +
> + /* DPLL okay; verify the cdclock
> + *
> + * Noticed in some instances that the freq selection is correct but
> + * decimal part is programmed wrong from BIOS where pre-os does not
> + * enable display. Verify the same as well.
> + */
> + cdctl = I915_READ(CDCLK_CTL);
> + expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
> + skl_cdclk_decimal(dev_priv->cdclk_freq);
> + if (cdctl == expected)
> + /* All well; nothing to sanitize */
> + return;
> +
> +sanitize:
> + DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> +
> + /* force cdclk programming */
> + dev_priv->cdclk_freq = 0;
> + /* force full PLL disable + enable */
> + dev_priv->cdclk_pll.vco = -1;
> +}
> +
> +void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
> +{
> + skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
> +}
> +
> +void skl_init_cdclk(struct drm_i915_private *dev_priv)
> +{
> + int cdclk, vco;
> +
> + skl_sanitize_cdclk(dev_priv);
> +
> + if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.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);
> + return;
> + }
> +
> + vco = dev_priv->skl_preferred_vco_freq;
> + if (vco == 0)
> + vco = 8100000;
> + cdclk = skl_calc_cdclk(0, vco);
> +
> + skl_set_cdclk(dev_priv, cdclk, vco);
> +}
> +
> +static int bxt_calc_cdclk(int max_pixclk)
> +{
> + if (max_pixclk > 576000)
> + return 624000;
> + else if (max_pixclk > 384000)
> + return 576000;
> + else if (max_pixclk > 288000)
> + return 384000;
> + else if (max_pixclk > 144000)
> + return 288000;
> + else
> + return 144000;
> +}
> +
> +static int glk_calc_cdclk(int max_pixclk)
> +{
> + if (max_pixclk > 2 * 158400)
> + return 316800;
> + else if (max_pixclk > 2 * 79200)
> + return 158400;
> + else
> + return 79200;
> +}
> +
> +static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> +{
> + int ratio;
> +
> + if (cdclk == dev_priv->cdclk_pll.ref)
> + return 0;
> +
> + switch (cdclk) {
> + default:
> + MISSING_CASE(cdclk);
> + case 144000:
> + case 288000:
> + case 384000:
> + case 576000:
> + ratio = 60;
> + break;
> + case 624000:
> + ratio = 65;
> + break;
> + }
> +
> + return dev_priv->cdclk_pll.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)
> + return 0;
> +
> + switch (cdclk) {
> + default:
> + MISSING_CASE(cdclk);
> + case 79200:
> + case 158400:
> + case 316800:
> + ratio = 33;
> + break;
> + }
> +
> + return dev_priv->cdclk_pll.ref * ratio;
> +}
> +
> +static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> +{
> + u32 val;
> +
> + dev_priv->cdclk_pll.ref = 19200;
> + dev_priv->cdclk_pll.vco = 0;
> +
> + val = I915_READ(BXT_DE_PLL_ENABLE);
> + if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
> + return;
> +
> + if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
> + return;
> +
> + val = I915_READ(BXT_DE_PLL_CTL);
> + dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
> + dev_priv->cdclk_pll.ref;
> +}
> +
> +static int bxt_get_cdclk(struct drm_i915_private *dev_priv)
> +{
> + u32 divider;
> + int div, vco;
> +
> + bxt_de_pll_update(dev_priv);
> +
> + vco = dev_priv->cdclk_pll.vco;
> + if (vco == 0)
> + return dev_priv->cdclk_pll.ref;
> +
> + divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
> +
> + switch (divider) {
> + case BXT_CDCLK_CD2X_DIV_SEL_1:
> + div = 2;
> + break;
> + case BXT_CDCLK_CD2X_DIV_SEL_1_5:
> + WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> + div = 3;
> + break;
> + case BXT_CDCLK_CD2X_DIV_SEL_2:
> + div = 4;
> + break;
> + case BXT_CDCLK_CD2X_DIV_SEL_4:
> + div = 8;
> + break;
> + default:
> + MISSING_CASE(divider);
> + return dev_priv->cdclk_pll.ref;
> + }
> +
> + return DIV_ROUND_CLOSEST(vco, div);
> +}
> +
> +static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> +{
> + I915_WRITE(BXT_DE_PLL_ENABLE, 0);
> +
> + /* Timeout 200us */
> + if (intel_wait_for_register(dev_priv,
> + BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
> + 1))
> + DRM_ERROR("timeout waiting for DE PLL unlock\n");
> +
> + dev_priv->cdclk_pll.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);
> + u32 val;
> +
> + val = I915_READ(BXT_DE_PLL_CTL);
> + val &= ~BXT_DE_PLL_RATIO_MASK;
> + val |= BXT_DE_PLL_RATIO(ratio);
> + I915_WRITE(BXT_DE_PLL_CTL, val);
> +
> + I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
> +
> + /* Timeout 200us */
> + if (intel_wait_for_register(dev_priv,
> + BXT_DE_PLL_ENABLE,
> + BXT_DE_PLL_LOCK,
> + BXT_DE_PLL_LOCK,
> + 1))
> + DRM_ERROR("timeout waiting for DE PLL lock\n");
> +
> + dev_priv->cdclk_pll.vco = vco;
> +}
> +
> +static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> +{
> + u32 val, divider;
> + int vco, ret;
> +
> + if (IS_GEMINILAKE(dev_priv))
> + vco = glk_de_pll_vco(dev_priv, cdclk);
> + else
> + vco = bxt_de_pll_vco(dev_priv, cdclk);
> +
> + DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n",
> + cdclk, vco);
> +
> + /* cdclk = vco / 2 / div{1,1.5,2,4} */
> + switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
> + case 8:
> + divider = BXT_CDCLK_CD2X_DIV_SEL_4;
> + break;
> + case 4:
> + divider = BXT_CDCLK_CD2X_DIV_SEL_2;
> + break;
> + case 3:
> + WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> + divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
> + break;
> + case 2:
> + divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> + break;
> + default:
> + WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
> + WARN_ON(vco != 0);
> +
> + divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> + break;
> + }
> +
> + /* Inform power controller of upcoming frequency change */
> + mutex_lock(&dev_priv->rps.hw_lock);
> + ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> + 0x80000000);
> + mutex_unlock(&dev_priv->rps.hw_lock);
> +
> + if (ret) {
> + DRM_ERROR("PCode CDCLK freq change notify failed (err %d,
> freq %d)\n",
> + ret, cdclk);
> + return;
> + }
> +
> + if (dev_priv->cdclk_pll.vco != 0 &&
> + dev_priv->cdclk_pll.vco != vco)
> + bxt_de_pll_disable(dev_priv);
> +
> + if (dev_priv->cdclk_pll.vco != vco)
> + bxt_de_pll_enable(dev_priv, vco);
> +
> + val = divider | skl_cdclk_decimal(cdclk);
> + /*
> + * FIXME if only the cd2x divider needs changing, it could be done
> + * without shutting off the pipe (if only one pipe is active).
> + */
> + val |= BXT_CDCLK_CD2X_PIPE_NONE;
> + /*
> + * Disable SSA Precharge when CD clock frequency < 500 MHz,
> + * enable otherwise.
> + */
> + if (cdclk >= 500000)
> + val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> + I915_WRITE(CDCLK_CTL, val);
> +
> + mutex_lock(&dev_priv->rps.hw_lock);
> + ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> + DIV_ROUND_UP(cdclk, 25000));
> + mutex_unlock(&dev_priv->rps.hw_lock);
> +
> + if (ret) {
> + DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
> + ret, cdclk);
> + return;
> + }
> +
> + intel_update_cdclk(dev_priv);
> +}
> +
> +static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> +{
> + u32 cdctl, expected;
> +
> + intel_update_cdclk(dev_priv);
> +
> + if (dev_priv->cdclk_pll.vco == 0 ||
> + dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> + goto sanitize;
> +
> + /* DPLL okay; verify the cdclock
> + *
> + * Some BIOS versions leave an incorrect decimal frequency value and
> + * set reserved MBZ bits in CDCLK_CTL at least during exiting from
> S4,
> + * so sanitize this register.
> + */
> + cdctl = I915_READ(CDCLK_CTL);
> + /*
> + * Let's ignore the pipe field, since BIOS could have configured the
> + * dividers both synching to an active pipe, or asynchronously
> + * (PIPE_NONE).
> + */
> + cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
> +
> + expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
> + skl_cdclk_decimal(dev_priv->cdclk_freq);
> + /*
> + * Disable SSA Precharge when CD clock frequency < 500 MHz,
> + * enable otherwise.
> + */
> + if (dev_priv->cdclk_freq >= 500000)
> + expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> +
> + if (cdctl == expected)
> + /* All well; nothing to sanitize */
> + return;
> +
> +sanitize:
> + DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> +
> + /* force cdclk programming */
> + dev_priv->cdclk_freq = 0;
> +
> + /* force full PLL disable + enable */
> + dev_priv->cdclk_pll.vco = -1;
> +}
> +
> +void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> +{
> + int cdclk;
> +
> + bxt_sanitize_cdclk(dev_priv);
> +
> + if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
> + return;
> +
> + /*
> + * FIXME:
> + * - The initial CDCLK needs to be read from VBT.
> + * Need to make this change after VBT has changes for BXT.
> + */
> + if (IS_GEMINILAKE(dev_priv))
> + cdclk = glk_calc_cdclk(0);
> + else
> + cdclk = bxt_calc_cdclk(0);
> +
> + bxt_set_cdclk(dev_priv, cdclk);
> +}
> +
> +void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
> +{
> + bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
> +}
> +
> +static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state
> *crtc_state,
> + int pixel_rate)
> +{
> + struct drm_i915_private *dev_priv =
> + to_i915(crtc_state->base.crtc->dev);
> +
> + /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
> + if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
> + pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
> +
> + /* BSpec says "Do not use DisplayPort with CDCLK less than
> + * 432 MHz, audio enabled, port width x4, and link rate
> + * HBR2 (5.4 GHz), or else there may be audio corruption or
> + * screen corruption."
> + */
> + if (intel_crtc_has_dp_encoder(crtc_state) &&
> + crtc_state->has_audio &&
> + crtc_state->port_clock >= 540000 &&
> + crtc_state->lane_count == 4)
> + pixel_rate = max(432000, pixel_rate);
> +
> + return pixel_rate;
> +}
> +
> +/* compute the max rate for new configuration */
> +static int intel_max_pixel_rate(struct drm_atomic_state *state)
> +{
> + struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> + struct drm_i915_private *dev_priv = to_i915(state->dev);
> + struct drm_crtc *crtc;
> + struct drm_crtc_state *cstate;
> + struct intel_crtc_state *crtc_state;
> + unsigned int max_pixel_rate = 0, i;
> + enum pipe pipe;
> +
> + memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
> + sizeof(intel_state->min_pixclk));
> +
> + for_each_crtc_in_state(state, crtc, cstate, i) {
> + int pixel_rate;
> +
> + crtc_state = to_intel_crtc_state(cstate);
> + if (!crtc_state->base.enable) {
> + intel_state->min_pixclk[i] = 0;
> + continue;
> + }
> +
> + pixel_rate = crtc_state->pixel_rate;
> +
> + if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
> + pixel_rate =
> + bdw_adjust_min_pipe_pixel_rate(crtc_state,
> + pixel_rate);
> +
> + intel_state->min_pixclk[i] = pixel_rate;
> + }
> +
> + for_each_pipe(dev_priv, pipe)
> + max_pixel_rate = max(intel_state->min_pixclk[pipe],
> + max_pixel_rate);
> +
> + return max_pixel_rate;
> +}
> +
> +static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> + struct drm_device *dev = state->dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + int max_pixclk = intel_max_pixel_rate(state);
> + struct intel_atomic_state *intel_state =
> + to_intel_atomic_state(state);
> +
> + intel_state->cdclk = intel_state->dev_cdclk =
> + vlv_calc_cdclk(dev_priv, max_pixclk);
> +
> + if (!intel_state->active_crtcs)
> + intel_state->dev_cdclk = vlv_calc_cdclk(dev_priv, 0);
> +
> + return 0;
> +}
> +
> +static void vlv_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> + struct drm_device *dev = old_state->dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + struct intel_atomic_state *old_intel_state =
> + to_intel_atomic_state(old_state);
> + unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +
> + /*
> + * FIXME: We can end up here with all power domains off, yet
> + * with a CDCLK frequency other than the minimum. To account
> + * for this take the PIPE-A power domain, which covers the HW
> + * blocks needed for the following programming. This can be
> + * removed once it's guaranteed that we get here either with
> + * the minimum CDCLK set, or the required power domains
> + * enabled.
> + */
> + intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> +
> + if (IS_CHERRYVIEW(dev_priv))
> + chv_set_cdclk(dev, req_cdclk);
> + else
> + vlv_set_cdclk(dev, req_cdclk);
> +
> + vlv_program_pfi_credits(dev_priv);
> +
> + intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> +}
> +
> +static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> + struct drm_i915_private *dev_priv = to_i915(state->dev);
> + struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> + int max_pixclk = intel_max_pixel_rate(state);
> + int cdclk;
> +
> + /*
> + * FIXME should also account for plane ratio
> + * once 64bpp pixel formats are supported.
> + */
> + cdclk = bdw_calc_cdclk(max_pixclk);
> +
> + if (cdclk > dev_priv->max_cdclk_freq) {
> + DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d
> kHz)\n",
> + cdclk, dev_priv->max_cdclk_freq);
> + return -EINVAL;
> + }
> +
> + intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> + if (!intel_state->active_crtcs)
> + intel_state->dev_cdclk = bdw_calc_cdclk(0);
> +
> + return 0;
> +}
> +
> +static void bdw_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> + struct drm_device *dev = old_state->dev;
> + struct intel_atomic_state *old_intel_state =
> + to_intel_atomic_state(old_state);
> + unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +
> + bdw_set_cdclk(dev, req_cdclk);
> +}
> +
> +static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> + struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> + struct drm_i915_private *dev_priv = to_i915(state->dev);
> + const int max_pixclk = intel_max_pixel_rate(state);
> + int vco = intel_state->cdclk_pll_vco;
> + int cdclk;
> +
> + /*
> + * FIXME should also account for plane ratio
> + * once 64bpp pixel formats are supported.
> + */
> + cdclk = skl_calc_cdclk(max_pixclk, vco);
> +
> + /*
> + * 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;
> + }
> +
> + intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> + if (!intel_state->active_crtcs)
> + intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
> +
> + return 0;
> +}
> +
> +static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> + struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> + struct intel_atomic_state *intel_state =
> + to_intel_atomic_state(old_state);
> + unsigned int req_cdclk = intel_state->dev_cdclk;
> + unsigned int req_vco = intel_state->cdclk_pll_vco;
> +
> + skl_set_cdclk(dev_priv, req_cdclk, req_vco);
> +}
> +
> +static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> + struct drm_i915_private *dev_priv = to_i915(state->dev);
> + int max_pixclk = intel_max_pixel_rate(state);
> + struct intel_atomic_state *intel_state =
> + to_intel_atomic_state(state);
> + int cdclk;
> +
> + if (IS_GEMINILAKE(dev_priv))
> + cdclk = glk_calc_cdclk(max_pixclk);
> + else
> + cdclk = bxt_calc_cdclk(max_pixclk);
> +
> + intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> +
> + if (!intel_state->active_crtcs) {
> + if (IS_GEMINILAKE(dev_priv))
> + cdclk = glk_calc_cdclk(0);
> + else
> + cdclk = bxt_calc_cdclk(0);
> +
> + intel_state->dev_cdclk = cdclk;
> + }
> +
> + return 0;
> +}
> +
> +static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> +{
> + struct drm_device *dev = old_state->dev;
> + struct intel_atomic_state *old_intel_state =
> + to_intel_atomic_state(old_state);
> + unsigned int req_cdclk = old_intel_state->dev_cdclk;
> +
> + bxt_set_cdclk(to_i915(dev), req_cdclk);
> +}
> +
> +static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
> +{
> + int max_cdclk_freq = dev_priv->max_cdclk_freq;
> +
> + if (IS_GEMINILAKE(dev_priv))
> + return 2 * max_cdclk_freq;
> + else if (INTEL_INFO(dev_priv)->gen >= 9 ||
> + IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> + return max_cdclk_freq;
> + else if (IS_CHERRYVIEW(dev_priv))
> + return max_cdclk_freq*95/100;
> + else if (INTEL_INFO(dev_priv)->gen < 4)
> + return 2*max_cdclk_freq*90/100;
> + else
> + return max_cdclk_freq*90/100;
> +}
> +
> +void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> +{
> + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> + u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
> + int max_cdclk, vco;
> +
> + vco = dev_priv->skl_preferred_vco_freq;
> + WARN_ON(vco != 8100000 && vco != 8640000);
> +
> + /*
> + * Use the lower (vco 8640) cdclk values as a
> + * first guess. skl_calc_cdclk() will correct it
> + * if the preferred vco is 8100 instead.
> + */
> + if (limit == SKL_DFSM_CDCLK_LIMIT_675)
> + max_cdclk = 617143;
> + else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
> + max_cdclk = 540000;
> + else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
> + max_cdclk = 432000;
> + else
> + max_cdclk = 308571;
> +
> + dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
> + } else if (IS_GEMINILAKE(dev_priv)) {
> + dev_priv->max_cdclk_freq = 316800;
> + } else if (IS_BROXTON(dev_priv)) {
> + dev_priv->max_cdclk_freq = 624000;
> + } else if (IS_BROADWELL(dev_priv)) {
> + /*
> + * FIXME with extra cooling we can allow
> + * 540 MHz for ULX and 675 Mhz for ULT.
> + * How can we know if extra cooling is
> + * available? PCI ID, VTB, something else?
> + */
> + if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> + dev_priv->max_cdclk_freq = 450000;
> + else if (IS_BDW_ULX(dev_priv))
> + dev_priv->max_cdclk_freq = 450000;
> + else if (IS_BDW_ULT(dev_priv))
> + dev_priv->max_cdclk_freq = 540000;
> + else
> + dev_priv->max_cdclk_freq = 675000;
> + } else if (IS_CHERRYVIEW(dev_priv)) {
> + dev_priv->max_cdclk_freq = 320000;
> + } else if (IS_VALLEYVIEW(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_dotclk_freq = intel_compute_max_dotclk(dev_priv);
> +
> + DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
> + dev_priv->max_cdclk_freq);
> +
> + DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
> + dev_priv->max_dotclk_freq);
> +}
> +
> +void intel_update_cdclk(struct drm_i915_private *dev_priv)
> +{
> + dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
> +
> + 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);
> +
> + /*
> + * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
> + * Programmng [sic] note: bit[9:2] should be programmed to the number
> + * of cdclk that generates 4MHz reference clock freq which is used to
> + * generate GMBus clock. This will vary with the cdclk freq.
> + */
> + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> + I915_WRITE(GMBUSFREQ_VLV,
> + DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
> +}
> +
> +static int pch_rawclk(struct drm_i915_private *dev_priv)
> +{
> + return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
> +}
> +
> +static int vlv_hrawclk(struct drm_i915_private *dev_priv)
> +{
> + /* RAWCLK_FREQ_VLV register updated from power well code */
> + return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
> + CCK_DISPLAY_REF_CLOCK_CONTROL);
> +}
> +
> +static int g4x_hrawclk(struct drm_i915_private *dev_priv)
> +{
> + uint32_t clkcfg;
> +
> + /* hrawclock is 1/4 the FSB frequency */
> + clkcfg = I915_READ(CLKCFG);
> + switch (clkcfg & CLKCFG_FSB_MASK) {
> + case CLKCFG_FSB_400:
> + return 100000;
> + case CLKCFG_FSB_533:
> + return 133333;
> + case CLKCFG_FSB_667:
> + return 166667;
> + case CLKCFG_FSB_800:
> + return 200000;
> + case CLKCFG_FSB_1067:
> + return 266667;
> + case CLKCFG_FSB_1333:
> + return 333333;
> + /* these two are just a guess; one of them might be right */
> + case CLKCFG_FSB_1600:
> + case CLKCFG_FSB_1600_ALT:
> + return 400000;
> + default:
> + return 133333;
> + }
> +}
> +
> +void intel_update_rawclk(struct drm_i915_private *dev_priv)
> +{
> + if (HAS_PCH_SPLIT(dev_priv))
> + dev_priv->rawclk_freq = pch_rawclk(dev_priv);
> + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> + dev_priv->rawclk_freq = vlv_hrawclk(dev_priv);
> + else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
> + dev_priv->rawclk_freq = g4x_hrawclk(dev_priv);
> + else
> + /* no rawclk on other platforms, or no need to know it */
> + return;
> +
> + DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
> +}
> +
> +void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
> +{
> + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> + dev_priv->display.modeset_commit_cdclk =
> + vlv_modeset_commit_cdclk;
> + dev_priv->display.modeset_calc_cdclk =
> + vlv_modeset_calc_cdclk;
> + } else if (IS_BROADWELL(dev_priv)) {
> + dev_priv->display.modeset_commit_cdclk =
> + bdw_modeset_commit_cdclk;
> + dev_priv->display.modeset_calc_cdclk =
> + bdw_modeset_calc_cdclk;
> + } else if (IS_GEN9_LP(dev_priv)) {
> + dev_priv->display.modeset_commit_cdclk =
> + bxt_modeset_commit_cdclk;
> + dev_priv->display.modeset_calc_cdclk =
> + bxt_modeset_calc_cdclk;
> + } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> + dev_priv->display.modeset_commit_cdclk =
> + skl_modeset_commit_cdclk;
> + dev_priv->display.modeset_calc_cdclk =
> + skl_modeset_calc_cdclk;
> + }
> +
> + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> + dev_priv->display.get_cdclk = skl_get_cdclk;
> + else if (IS_GEN9_LP(dev_priv))
> + dev_priv->display.get_cdclk = bxt_get_cdclk;
> + else if (IS_BROADWELL(dev_priv))
> + dev_priv->display.get_cdclk = bdw_get_cdclk;
> + else if (IS_HASWELL(dev_priv))
> + dev_priv->display.get_cdclk = hsw_get_cdclk;
> + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> + dev_priv->display.get_cdclk = vlv_get_cdclk;
> + else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
> + dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> + else if (IS_GEN5(dev_priv))
> + dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
> + else if (IS_GM45(dev_priv))
> + dev_priv->display.get_cdclk = gm45_get_cdclk;
> + else if (IS_G4X(dev_priv))
> + dev_priv->display.get_cdclk = g33_get_cdclk;
> + else if (IS_I965GM(dev_priv))
> + dev_priv->display.get_cdclk = i965gm_get_cdclk;
> + else if (IS_I965G(dev_priv))
> + dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> + else if (IS_PINEVIEW(dev_priv))
> + dev_priv->display.get_cdclk = pnv_get_cdclk;
> + else if (IS_G33(dev_priv))
> + dev_priv->display.get_cdclk = g33_get_cdclk;
> + else if (IS_I945GM(dev_priv))
> + dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> + else if (IS_I945G(dev_priv))
> + dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> + else if (IS_I915GM(dev_priv))
> + dev_priv->display.get_cdclk = i915gm_get_cdclk;
> + else if (IS_I915G(dev_priv))
> + dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
> + else if (IS_I865G(dev_priv))
> + dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
> + else if (IS_I85X(dev_priv))
> + dev_priv->display.get_cdclk = i85x_get_cdclk;
> + else if (IS_I845G(dev_priv))
> + dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> + else { /* 830 */
> + WARN(!IS_I830(dev_priv),
> + "Unknown platform. Assuming 133 MHz CDCLK\n");
> + dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
> + }
> +}
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 29f91e799272..519e5d663c5f 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -123,9 +123,6 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc,
> bool force);
> static void ironlake_pfit_enable(struct intel_crtc *crtc);
> static void intel_modeset_setup_hw_state(struct drm_device *dev);
> static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
> -static int intel_max_pixel_rate(struct drm_atomic_state *state);
> -static int glk_calc_cdclk(int max_pixclk);
> -static int bxt_calc_cdclk(int max_pixclk);
>
> struct intel_limit {
> struct {
> @@ -171,8 +168,8 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
> return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
> }
>
> -static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
> - const char *name, u32 reg)
> +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);
> @@ -181,63 +178,6 @@ static int vlv_get_cck_clock_hpll(struct drm_i915_private
> *dev_priv,
> dev_priv->hpll_freq);
> }
>
> -static int
> -intel_pch_rawclk(struct drm_i915_private *dev_priv)
> -{
> - return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
> -}
> -
> -static int
> -intel_vlv_hrawclk(struct drm_i915_private *dev_priv)
> -{
> - /* RAWCLK_FREQ_VLV register updated from power well code */
> - return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
> - CCK_DISPLAY_REF_CLOCK_CONTROL);
> -}
> -
> -static int
> -intel_g4x_hrawclk(struct drm_i915_private *dev_priv)
> -{
> - uint32_t clkcfg;
> -
> - /* hrawclock is 1/4 the FSB frequency */
> - clkcfg = I915_READ(CLKCFG);
> - switch (clkcfg & CLKCFG_FSB_MASK) {
> - case CLKCFG_FSB_400:
> - return 100000;
> - case CLKCFG_FSB_533:
> - return 133333;
> - case CLKCFG_FSB_667:
> - return 166667;
> - case CLKCFG_FSB_800:
> - return 200000;
> - case CLKCFG_FSB_1067:
> - return 266667;
> - case CLKCFG_FSB_1333:
> - return 333333;
> - /* these two are just a guess; one of them might be right */
> - case CLKCFG_FSB_1600:
> - case CLKCFG_FSB_1600_ALT:
> - return 400000;
> - default:
> - return 133333;
> - }
> -}
> -
> -void intel_update_rawclk(struct drm_i915_private *dev_priv)
> -{
> - if (HAS_PCH_SPLIT(dev_priv))
> - dev_priv->rawclk_freq = intel_pch_rawclk(dev_priv);
> - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> - dev_priv->rawclk_freq = intel_vlv_hrawclk(dev_priv);
> - else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
> - dev_priv->rawclk_freq = intel_g4x_hrawclk(dev_priv);
> - else
> - return; /* no rawclk on other platforms, or no need to know
> it */
> -
> - DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
> -}
> -
> static void intel_update_czclk(struct drm_i915_private *dev_priv)
> {
> if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
> @@ -5791,1092 +5731,210 @@ static void modeset_put_power_domains(struct
> drm_i915_private *dev_priv,
> intel_display_power_put(dev_priv, domain);
> }
>
> -static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
> +static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> + struct drm_atomic_state *old_state)
> {
> - int max_cdclk_freq = dev_priv->max_cdclk_freq;
> + struct drm_crtc *crtc = pipe_config->base.crtc;
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + int pipe = intel_crtc->pipe;
>
> - if (IS_GEMINILAKE(dev_priv))
> - return 2 * max_cdclk_freq;
> - else if (INTEL_INFO(dev_priv)->gen >= 9 ||
> - IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> - return max_cdclk_freq;
> - else if (IS_CHERRYVIEW(dev_priv))
> - return max_cdclk_freq*95/100;
> - else if (INTEL_INFO(dev_priv)->gen < 4)
> - return 2*max_cdclk_freq*90/100;
> - else
> - return max_cdclk_freq*90/100;
> -}
> + if (WARN_ON(intel_crtc->active))
> + return;
>
> -static int skl_calc_cdclk(int max_pixclk, int vco);
> + if (intel_crtc_has_dp_encoder(intel_crtc->config))
> + intel_dp_set_m_n(intel_crtc, M1_N1);
>
> -static void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
> -{
> - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> - u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
> - int max_cdclk, vco;
> + intel_set_pipe_timings(intel_crtc);
> + intel_set_pipe_src_size(intel_crtc);
>
> - vco = dev_priv->skl_preferred_vco_freq;
> - WARN_ON(vco != 8100000 && vco != 8640000);
> + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> + struct drm_i915_private *dev_priv = to_i915(dev);
>
> - /*
> - * Use the lower (vco 8640) cdclk values as a
> - * first guess. skl_calc_cdclk() will correct it
> - * if the preferred vco is 8100 instead.
> - */
> - if (limit == SKL_DFSM_CDCLK_LIMIT_675)
> - max_cdclk = 617143;
> - else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
> - max_cdclk = 540000;
> - else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
> - max_cdclk = 432000;
> - else
> - max_cdclk = 308571;
> -
> - dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
> - } else if (IS_GEMINILAKE(dev_priv)) {
> - dev_priv->max_cdclk_freq = 316800;
> - } else if (IS_BROXTON(dev_priv)) {
> - dev_priv->max_cdclk_freq = 624000;
> - } else if (IS_BROADWELL(dev_priv)) {
> - /*
> - * FIXME with extra cooling we can allow
> - * 540 MHz for ULX and 675 Mhz for ULT.
> - * How can we know if extra cooling is
> - * available? PCI ID, VTB, something else?
> - */
> - if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> - dev_priv->max_cdclk_freq = 450000;
> - else if (IS_BDW_ULX(dev_priv))
> - dev_priv->max_cdclk_freq = 450000;
> - else if (IS_BDW_ULT(dev_priv))
> - dev_priv->max_cdclk_freq = 540000;
> - else
> - dev_priv->max_cdclk_freq = 675000;
> - } else if (IS_CHERRYVIEW(dev_priv)) {
> - dev_priv->max_cdclk_freq = 320000;
> - } else if (IS_VALLEYVIEW(dev_priv)) {
> - dev_priv->max_cdclk_freq = 400000;
> - } else {
> - /* otherwise assume cdclk is fixed */
> - dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
> + I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
> + I915_WRITE(CHV_CANVAS(pipe), 0);
> }
>
> - dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
> -
> - DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
> - dev_priv->max_cdclk_freq);
> -
> - DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
> - dev_priv->max_dotclk_freq);
> -}
> -
> -static void intel_update_cdclk(struct drm_i915_private *dev_priv)
> -{
> - dev_priv->cdclk_freq = dev_priv->display.get_cdclk(dev_priv);
> -
> - 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);
> -
> - /*
> - * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
> - * Programmng [sic] note: bit[9:2] should be programmed to the number
> - * of cdclk that generates 4MHz reference clock freq which is used to
> - * generate GMBus clock. This will vary with the cdclk freq.
> - */
> - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> - I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq,
> 1000));
> -}
> + i9xx_set_pipeconf(intel_crtc);
>
> -/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
> -static int skl_cdclk_decimal(int cdclk)
> -{
> - return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
> -}
> + intel_crtc->active = true;
>
> -static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> -{
> - int ratio;
> + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
>
> - if (cdclk == dev_priv->cdclk_pll.ref)
> - return 0;
> + intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
>
> - switch (cdclk) {
> - default:
> - MISSING_CASE(cdclk);
> - case 144000:
> - case 288000:
> - case 384000:
> - case 576000:
> - ratio = 60;
> - break;
> - case 624000:
> - ratio = 65;
> - break;
> + if (IS_CHERRYVIEW(dev_priv)) {
> + chv_prepare_pll(intel_crtc, intel_crtc->config);
> + chv_enable_pll(intel_crtc, intel_crtc->config);
> + } else {
> + vlv_prepare_pll(intel_crtc, intel_crtc->config);
> + vlv_enable_pll(intel_crtc, intel_crtc->config);
> }
>
> - return dev_priv->cdclk_pll.ref * ratio;
> -}
> + intel_encoders_pre_enable(crtc, pipe_config, old_state);
>
> -static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> -{
> - int ratio;
> + i9xx_pfit_enable(intel_crtc);
>
> - if (cdclk == dev_priv->cdclk_pll.ref)
> - return 0;
> + intel_color_load_luts(&pipe_config->base);
>
> - switch (cdclk) {
> - default:
> - MISSING_CASE(cdclk);
> - case 79200:
> - case 158400:
> - case 316800:
> - ratio = 33;
> - break;
> - }
> + intel_update_watermarks(intel_crtc);
> + intel_enable_pipe(intel_crtc);
> +
> + assert_vblank_disabled(crtc);
> + drm_crtc_vblank_on(crtc);
>
> - return dev_priv->cdclk_pll.ref * ratio;
> + intel_encoders_enable(crtc, pipe_config, old_state);
> }
>
> -static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
> +static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
> {
> - I915_WRITE(BXT_DE_PLL_ENABLE, 0);
> -
> - /* Timeout 200us */
> - if (intel_wait_for_register(dev_priv,
> - BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
> - 1))
> - DRM_ERROR("timeout waiting for DE PLL unlock\n");
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
>
> - dev_priv->cdclk_pll.vco = 0;
> + I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
> + I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
> }
>
> -static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
> +static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
> + struct drm_atomic_state *old_state)
> {
> - int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
> - u32 val;
> + struct drm_crtc *crtc = pipe_config->base.crtc;
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + enum pipe pipe = intel_crtc->pipe;
>
> - val = I915_READ(BXT_DE_PLL_CTL);
> - val &= ~BXT_DE_PLL_RATIO_MASK;
> - val |= BXT_DE_PLL_RATIO(ratio);
> - I915_WRITE(BXT_DE_PLL_CTL, val);
> + if (WARN_ON(intel_crtc->active))
> + return;
>
> - I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
> + i9xx_set_pll_dividers(intel_crtc);
>
> - /* Timeout 200us */
> - if (intel_wait_for_register(dev_priv,
> - BXT_DE_PLL_ENABLE,
> - BXT_DE_PLL_LOCK,
> - BXT_DE_PLL_LOCK,
> - 1))
> - DRM_ERROR("timeout waiting for DE PLL lock\n");
> + if (intel_crtc_has_dp_encoder(intel_crtc->config))
> + intel_dp_set_m_n(intel_crtc, M1_N1);
>
> - dev_priv->cdclk_pll.vco = vco;
> -}
> + intel_set_pipe_timings(intel_crtc);
> + intel_set_pipe_src_size(intel_crtc);
>
> -static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
> -{
> - u32 val, divider;
> - int vco, ret;
> + i9xx_set_pipeconf(intel_crtc);
>
> - if (IS_GEMINILAKE(dev_priv))
> - vco = glk_de_pll_vco(dev_priv, cdclk);
> - else
> - vco = bxt_de_pll_vco(dev_priv, cdclk);
> + intel_crtc->active = true;
>
> - DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk,
> vco);
> + if (!IS_GEN2(dev_priv))
> + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
>
> - /* cdclk = vco / 2 / div{1,1.5,2,4} */
> - switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
> - case 8:
> - divider = BXT_CDCLK_CD2X_DIV_SEL_4;
> - break;
> - case 4:
> - divider = BXT_CDCLK_CD2X_DIV_SEL_2;
> - break;
> - case 3:
> - WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> - divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
> - break;
> - case 2:
> - divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> - break;
> - default:
> - WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
> - WARN_ON(vco != 0);
> + intel_encoders_pre_enable(crtc, pipe_config, old_state);
>
> - divider = BXT_CDCLK_CD2X_DIV_SEL_1;
> - break;
> - }
> + i9xx_enable_pll(intel_crtc);
>
> - /* Inform power controller of upcoming frequency change */
> - mutex_lock(&dev_priv->rps.hw_lock);
> - ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> - 0x80000000);
> - mutex_unlock(&dev_priv->rps.hw_lock);
> + i9xx_pfit_enable(intel_crtc);
>
> - if (ret) {
> - DRM_ERROR("PCode CDCLK freq change notify failed (err %d,
> freq %d)\n",
> - ret, cdclk);
> - return;
> - }
> + intel_color_load_luts(&pipe_config->base);
>
> - if (dev_priv->cdclk_pll.vco != 0 &&
> - dev_priv->cdclk_pll.vco != vco)
> - bxt_de_pll_disable(dev_priv);
> + intel_update_watermarks(intel_crtc);
> + intel_enable_pipe(intel_crtc);
>
> - if (dev_priv->cdclk_pll.vco != vco)
> - bxt_de_pll_enable(dev_priv, vco);
> + assert_vblank_disabled(crtc);
> + drm_crtc_vblank_on(crtc);
>
> - val = divider | skl_cdclk_decimal(cdclk);
> - /*
> - * FIXME if only the cd2x divider needs changing, it could be done
> - * without shutting off the pipe (if only one pipe is active).
> - */
> - val |= BXT_CDCLK_CD2X_PIPE_NONE;
> - /*
> - * Disable SSA Precharge when CD clock frequency < 500 MHz,
> - * enable otherwise.
> - */
> - if (cdclk >= 500000)
> - val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> - I915_WRITE(CDCLK_CTL, val);
> + intel_encoders_enable(crtc, pipe_config, old_state);
> +}
>
> - mutex_lock(&dev_priv->rps.hw_lock);
> - ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
> - DIV_ROUND_UP(cdclk, 25000));
> - mutex_unlock(&dev_priv->rps.hw_lock);
> +static void i9xx_pfit_disable(struct intel_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
>
> - if (ret) {
> - DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
> - ret, cdclk);
> + if (!crtc->config->gmch_pfit.control)
> return;
> - }
>
> - intel_update_cdclk(dev_priv);
> + assert_pipe_disabled(dev_priv, crtc->pipe);
> +
> + DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
> + I915_READ(PFIT_CONTROL));
> + I915_WRITE(PFIT_CONTROL, 0);
> }
>
> -static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
> +static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
> + struct drm_atomic_state *old_state)
> {
> - u32 cdctl, expected;
> -
> - intel_update_cdclk(dev_priv);
> -
> - if (dev_priv->cdclk_pll.vco == 0 ||
> - dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> - goto sanitize;
> -
> - /* DPLL okay; verify the cdclock
> - *
> - * Some BIOS versions leave an incorrect decimal frequency value and
> - * set reserved MBZ bits in CDCLK_CTL at least during exiting from
> S4,
> - * so sanitize this register.
> - */
> - cdctl = I915_READ(CDCLK_CTL);
> - /*
> - * Let's ignore the pipe field, since BIOS could have configured the
> - * dividers both synching to an active pipe, or asynchronously
> - * (PIPE_NONE).
> - */
> - cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
> + struct drm_crtc *crtc = old_crtc_state->base.crtc;
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + int pipe = intel_crtc->pipe;
>
> - expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
> - skl_cdclk_decimal(dev_priv->cdclk_freq);
> /*
> - * Disable SSA Precharge when CD clock frequency < 500 MHz,
> - * enable otherwise.
> + * On gen2 planes are double buffered but the pipe isn't, so we must
> + * wait for planes to fully turn off before disabling the pipe.
> */
> - if (dev_priv->cdclk_freq >= 500000)
> - expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
> -
> - if (cdctl == expected)
> - /* All well; nothing to sanitize */
> - return;
> + if (IS_GEN2(dev_priv))
> + intel_wait_for_vblank(dev_priv, pipe);
>
> -sanitize:
> - DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> + intel_encoders_disable(crtc, old_crtc_state, old_state);
>
> - /* force cdclk programming */
> - dev_priv->cdclk_freq = 0;
> + drm_crtc_vblank_off(crtc);
> + assert_vblank_disabled(crtc);
>
> - /* force full PLL disable + enable */
> - dev_priv->cdclk_pll.vco = -1;
> -}
> + intel_disable_pipe(intel_crtc);
>
> -void bxt_init_cdclk(struct drm_i915_private *dev_priv)
> -{
> - int cdclk;
> + i9xx_pfit_disable(intel_crtc);
>
> - bxt_sanitize_cdclk(dev_priv);
> + intel_encoders_post_disable(crtc, old_crtc_state, old_state);
>
> - if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
> - return;
> + if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
> + if (IS_CHERRYVIEW(dev_priv))
> + chv_disable_pll(dev_priv, pipe);
> + else if (IS_VALLEYVIEW(dev_priv))
> + vlv_disable_pll(dev_priv, pipe);
> + else
> + i9xx_disable_pll(intel_crtc);
> + }
>
> - /*
> - * FIXME:
> - * - The initial CDCLK needs to be read from VBT.
> - * Need to make this change after VBT has changes for BXT.
> - */
> - if (IS_GEMINILAKE(dev_priv))
> - cdclk = glk_calc_cdclk(0);
> - else
> - cdclk = bxt_calc_cdclk(0);
> + intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
>
> - bxt_set_cdclk(dev_priv, cdclk);
> + if (!IS_GEN2(dev_priv))
> + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> }
>
> -void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
> +static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
> {
> - bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
> -}
> + struct intel_encoder *encoder;
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> + enum intel_display_power_domain domain;
> + unsigned long domains;
> + struct drm_atomic_state *state;
> + struct intel_crtc_state *crtc_state;
> + int ret;
>
> -static int skl_calc_cdclk(int max_pixclk, int vco)
> -{
> - if (vco == 8640000) {
> - if (max_pixclk > 540000)
> - return 617143;
> - else if (max_pixclk > 432000)
> - return 540000;
> - else if (max_pixclk > 308571)
> - return 432000;
> - else
> - return 308571;
> - } else {
> - if (max_pixclk > 540000)
> - return 675000;
> - else if (max_pixclk > 450000)
> - return 540000;
> - else if (max_pixclk > 337500)
> - return 450000;
> - else
> - return 337500;
> - }
> -}
> + if (!intel_crtc->active)
> + return;
>
> -static void
> -skl_dpll0_update(struct drm_i915_private *dev_priv)
> -{
> - u32 val;
> + if (to_intel_plane_state(crtc->primary->state)->base.visible) {
> + WARN_ON(intel_crtc->flip_work);
>
> - dev_priv->cdclk_pll.ref = 24000;
> - dev_priv->cdclk_pll.vco = 0;
> + intel_pre_disable_primary_noatomic(crtc);
>
> - val = I915_READ(LCPLL1_CTL);
> - if ((val & LCPLL_PLL_ENABLE) == 0)
> - return;
> + intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc-
> >primary));
> + to_intel_plane_state(crtc->primary->state)->base.visible =
> false;
> + }
>
> - if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
> - return;
> + state = drm_atomic_state_alloc(crtc->dev);
> + state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
>
> - val = I915_READ(DPLL_CTRL1);
> + /* Everything's already locked, -EDEADLK can't happen. */
> + crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
> + ret = drm_atomic_add_affected_connectors(state, crtc);
>
> - if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
> - DPLL_CTRL1_SSC(SKL_DPLL0) |
> - DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
> - DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
> - return;
> + WARN_ON(IS_ERR(crtc_state) || ret);
>
> - switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
> - case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
> - 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;
> - 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;
> - break;
> - default:
> - MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> - break;
> - }
> -}
> + dev_priv->display.crtc_disable(crtc_state, state);
>
> -void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
> -{
> - bool changed = dev_priv->skl_preferred_vco_freq != vco;
> + drm_atomic_state_put(state);
>
> - dev_priv->skl_preferred_vco_freq = vco;
> -
> - if (changed)
> - intel_update_max_cdclk(dev_priv);
> -}
> -
> -static void
> -skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
> -{
> - int min_cdclk = skl_calc_cdclk(0, vco);
> - u32 val;
> -
> - WARN_ON(vco != 8100000 && vco != 8640000);
> -
> - /* select the minimum CDCLK before enabling DPLL 0 */
> - val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
> - I915_WRITE(CDCLK_CTL, val);
> - POSTING_READ(CDCLK_CTL);
> -
> - /*
> - * We always enable DPLL0 with the lowest link rate possible, but
> still
> - * taking into account the VCO required to operate the eDP panel at
> the
> - * desired frequency. The usual DP link rates operate with a VCO of
> - * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
> - * The modeset code is responsible for the selection of the exact
> link
> - * rate later on, with the constraint of choosing a frequency that
> - * works with vco.
> - */
> - val = I915_READ(DPLL_CTRL1);
> -
> - val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0)
> |
> - DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
> - val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
> - if (vco == 8640000)
> - val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
> - SKL_DPLL0);
> - else
> - val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
> - SKL_DPLL0);
> -
> - I915_WRITE(DPLL_CTRL1, val);
> - POSTING_READ(DPLL_CTRL1);
> -
> - I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
> -
> - if (intel_wait_for_register(dev_priv,
> - LCPLL1_CTL, LCPLL_PLL_LOCK,
> LCPLL_PLL_LOCK,
> - 5))
> - DRM_ERROR("DPLL0 not locked\n");
> -
> - dev_priv->cdclk_pll.vco = vco;
> -
> - /* We'll want to keep using the current vco from now on. */
> - skl_set_preferred_cdclk_vco(dev_priv, vco);
> -}
> -
> -static void
> -skl_dpll0_disable(struct drm_i915_private *dev_priv)
> -{
> - I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
> - if (intel_wait_for_register(dev_priv,
> - LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
> - 1))
> - DRM_ERROR("Couldn't disable DPLL0\n");
> -
> - dev_priv->cdclk_pll.vco = 0;
> -}
> -
> -static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int
> vco)
> -{
> - u32 freq_select, pcu_ack;
> - int ret;
> -
> - WARN_ON((cdclk == 24000) != (vco == 0));
> -
> - DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk,
> vco);
> -
> - mutex_lock(&dev_priv->rps.hw_lock);
> - ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
> - SKL_CDCLK_PREPARE_FOR_CHANGE,
> - SKL_CDCLK_READY_FOR_CHANGE,
> - SKL_CDCLK_READY_FOR_CHANGE, 3);
> - mutex_unlock(&dev_priv->rps.hw_lock);
> - if (ret) {
> - DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
> - ret);
> - return;
> - }
> -
> - /* set CDCLK_CTL */
> - switch (cdclk) {
> - case 450000:
> - case 432000:
> - freq_select = CDCLK_FREQ_450_432;
> - pcu_ack = 1;
> - break;
> - case 540000:
> - freq_select = CDCLK_FREQ_540;
> - pcu_ack = 2;
> - break;
> - case 308571:
> - case 337500:
> - default:
> - freq_select = CDCLK_FREQ_337_308;
> - pcu_ack = 0;
> - break;
> - case 617143:
> - case 675000:
> - freq_select = CDCLK_FREQ_675_617;
> - pcu_ack = 3;
> - break;
> - }
> -
> - if (dev_priv->cdclk_pll.vco != 0 &&
> - dev_priv->cdclk_pll.vco != vco)
> - skl_dpll0_disable(dev_priv);
> -
> - if (dev_priv->cdclk_pll.vco != vco)
> - skl_dpll0_enable(dev_priv, vco);
> -
> - I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
> - POSTING_READ(CDCLK_CTL);
> -
> - /* inform PCU of the change */
> - mutex_lock(&dev_priv->rps.hw_lock);
> - sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
> - mutex_unlock(&dev_priv->rps.hw_lock);
> -
> - intel_update_cdclk(dev_priv);
> -}
> -
> -static void skl_sanitize_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);
> -}
> -
> -void skl_init_cdclk(struct drm_i915_private *dev_priv)
> -{
> - int cdclk, vco;
> -
> - skl_sanitize_cdclk(dev_priv);
> -
> - if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.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);
> - return;
> - }
> -
> - vco = dev_priv->skl_preferred_vco_freq;
> - if (vco == 0)
> - vco = 8100000;
> - cdclk = skl_calc_cdclk(0, vco);
> -
> - skl_set_cdclk(dev_priv, cdclk, vco);
> -}
> -
> -static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
> -{
> - uint32_t cdctl, expected;
> -
> - /*
> - * check if the pre-os intialized the display
> - * There is SWF18 scratchpad register defined which is set by the
> - * pre-os which can be used by the OS drivers to check the status
> - */
> - if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
> - goto sanitize;
> -
> - 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)
> - goto sanitize;
> -
> - /* DPLL okay; verify the cdclock
> - *
> - * Noticed in some instances that the freq selection is correct but
> - * decimal part is programmed wrong from BIOS where pre-os does not
> - * enable display. Verify the same as well.
> - */
> - cdctl = I915_READ(CDCLK_CTL);
> - expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
> - skl_cdclk_decimal(dev_priv->cdclk_freq);
> - if (cdctl == expected)
> - /* All well; nothing to sanitize */
> - return;
> -
> -sanitize:
> - DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> -
> - /* force cdclk programming */
> - dev_priv->cdclk_freq = 0;
> - /* force full PLL disable + enable */
> - dev_priv->cdclk_pll.vco = -1;
> -}
> -
> -/* Adjust CDclk dividers to allow high res or save power if possible */
> -static void valleyview_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)
> - cmd = 1;
> - else
> - cmd = 0;
> -
> - mutex_lock(&dev_priv->rps.hw_lock);
> - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> - val &= ~DSPFREQGUAR_MASK;
> - val |= (cmd << DSPFREQGUAR_SHIFT);
> - vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> - DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
> - 50)) {
> - DRM_ERROR("timed out waiting for CDclk change\n");
> - }
> - mutex_unlock(&dev_priv->rps.hw_lock);
> -
> - mutex_lock(&dev_priv->sb_lock);
> -
> - if (cdclk == 400000) {
> - u32 divider;
> -
> - divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk)
> - 1;
> -
> - /* adjust cdclk divider */
> - val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
> - val &= ~CCK_FREQUENCY_VALUES;
> - val |= divider;
> - vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
> -
> - if (wait_for((vlv_cck_read(dev_priv,
> CCK_DISPLAY_CLOCK_CONTROL) &
> - CCK_FREQUENCY_STATUS) == (divider <<
> CCK_FREQUENCY_STATUS_SHIFT),
> - 50))
> - DRM_ERROR("timed out waiting for CDclk change\n");
> - }
> -
> - /* adjust self-refresh exit latency value */
> - val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
> - val &= ~0x7f;
> -
> - /*
> - * For high bandwidth configs, we set a higher latency in the bunit
> - * so that the core display fetch happens in time to avoid underruns.
> - */
> - if (cdclk == 400000)
> - val |= 4500 / 250; /* 4.5 usec */
> - else
> - val |= 3000 / 250; /* 3.0 usec */
> - vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
> -
> - mutex_unlock(&dev_priv->sb_lock);
> -
> - intel_update_cdclk(dev_priv);
> -}
> -
> -static void cherryview_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:
> - case 266667:
> - case 200000:
> - break;
> - default:
> - MISSING_CASE(cdclk);
> - return;
> - }
> -
> - /*
> - * Specs are full of misinformation, but testing on actual
> - * hardware has shown that we just need to write the desired
> - * CCK divider into the Punit register.
> - */
> - cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
> -
> - mutex_lock(&dev_priv->rps.hw_lock);
> - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> - val &= ~DSPFREQGUAR_MASK_CHV;
> - val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
> - vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
> - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
> - DSPFREQSTAT_MASK_CHV) == (cmd <<
> DSPFREQSTAT_SHIFT_CHV),
> - 50)) {
> - DRM_ERROR("timed out waiting for CDclk change\n");
> - }
> - mutex_unlock(&dev_priv->rps.hw_lock);
> -
> - intel_update_cdclk(dev_priv);
> -}
> -
> -static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
> - int max_pixclk)
> -{
> - int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ? 333333 :
> 320000;
> - int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
> -
> - /*
> - * Really only a few cases to deal with, as only 4 CDclks are
> supported:
> - * 200MHz
> - * 267MHz
> - * 320/333MHz (depends on HPLL freq)
> - * 400MHz (VLV only)
> - * So we check to see whether we're above 90% (VLV) or 95% (CHV)
> - * of the lower bin and adjust if needed.
> - *
> - * We seem to get an unstable or solid color picture at 200MHz.
> - * Not sure what's wrong. For now use 200MHz only when all pipes
> - * are off.
> - */
> - if (!IS_CHERRYVIEW(dev_priv) &&
> - max_pixclk > freq_320*limit/100)
> - return 400000;
> - else if (max_pixclk > 266667*limit/100)
> - return freq_320;
> - else if (max_pixclk > 0)
> - return 266667;
> - else
> - return 200000;
> -}
> -
> -static int glk_calc_cdclk(int max_pixclk)
> -{
> - if (max_pixclk > 2 * 158400)
> - return 316800;
> - else if (max_pixclk > 2 * 79200)
> - return 158400;
> - else
> - return 79200;
> -}
> -
> -static int bxt_calc_cdclk(int max_pixclk)
> -{
> - if (max_pixclk > 576000)
> - return 624000;
> - else if (max_pixclk > 384000)
> - return 576000;
> - else if (max_pixclk > 288000)
> - return 384000;
> - else if (max_pixclk > 144000)
> - return 288000;
> - else
> - return 144000;
> -}
> -
> -static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> - struct drm_device *dev = state->dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - int max_pixclk = intel_max_pixel_rate(state);
> - struct intel_atomic_state *intel_state =
> - to_intel_atomic_state(state);
> -
> - intel_state->cdclk = intel_state->dev_cdclk =
> - valleyview_calc_cdclk(dev_priv, max_pixclk);
> -
> - if (!intel_state->active_crtcs)
> - intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0);
> -
> - return 0;
> -}
> -
> -static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> - struct drm_i915_private *dev_priv = to_i915(state->dev);
> - int max_pixclk = intel_max_pixel_rate(state);
> - struct intel_atomic_state *intel_state =
> - to_intel_atomic_state(state);
> - int cdclk;
> -
> - if (IS_GEMINILAKE(dev_priv))
> - cdclk = glk_calc_cdclk(max_pixclk);
> - else
> - cdclk = bxt_calc_cdclk(max_pixclk);
> -
> - intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> -
> - if (!intel_state->active_crtcs) {
> - if (IS_GEMINILAKE(dev_priv))
> - cdclk = glk_calc_cdclk(0);
> - else
> - cdclk = bxt_calc_cdclk(0);
> -
> - intel_state->dev_cdclk = cdclk;
> - }
> -
> - return 0;
> -}
> -
> -static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
> -{
> - unsigned int credits, default_credits;
> -
> - if (IS_CHERRYVIEW(dev_priv))
> - default_credits = PFI_CREDIT(12);
> - else
> - default_credits = PFI_CREDIT(8);
> -
> - if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
> - /* CHV suggested value is 31 or 63 */
> - if (IS_CHERRYVIEW(dev_priv))
> - credits = PFI_CREDIT_63;
> - else
> - credits = PFI_CREDIT(15);
> - } else {
> - credits = default_credits;
> - }
> -
> - /*
> - * WA - write default credits before re-programming
> - * FIXME: should we also set the resend bit here?
> - */
> - I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> - default_credits);
> -
> - I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
> - credits | PFI_CREDIT_RESEND);
> -
> - /*
> - * FIXME is this guaranteed to clear
> - * immediately or should we poll for it?
> - */
> - WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
> -}
> -
> -static void valleyview_modeset_commit_cdclk(struct drm_atomic_state
> *old_state)
> -{
> - struct drm_device *dev = old_state->dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - struct intel_atomic_state *old_intel_state =
> - to_intel_atomic_state(old_state);
> - unsigned req_cdclk = old_intel_state->dev_cdclk;
> -
> - /*
> - * FIXME: We can end up here with all power domains off, yet
> - * with a CDCLK frequency other than the minimum. To account
> - * for this take the PIPE-A power domain, which covers the HW
> - * blocks needed for the following programming. This can be
> - * removed once it's guaranteed that we get here either with
> - * the minimum CDCLK set, or the required power domains
> - * enabled.
> - */
> - intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> -
> - if (IS_CHERRYVIEW(dev_priv))
> - cherryview_set_cdclk(dev, req_cdclk);
> - else
> - valleyview_set_cdclk(dev, req_cdclk);
> -
> - vlv_program_pfi_credits(dev_priv);
> -
> - intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> -}
> -
> -static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> - struct drm_atomic_state *old_state)
> -{
> - struct drm_crtc *crtc = pipe_config->base.crtc;
> - struct drm_device *dev = crtc->dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> - int pipe = intel_crtc->pipe;
> -
> - if (WARN_ON(intel_crtc->active))
> - return;
> -
> - if (intel_crtc_has_dp_encoder(intel_crtc->config))
> - intel_dp_set_m_n(intel_crtc, M1_N1);
> -
> - intel_set_pipe_timings(intel_crtc);
> - intel_set_pipe_src_size(intel_crtc);
> -
> - if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> - struct drm_i915_private *dev_priv = to_i915(dev);
> -
> - I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
> - I915_WRITE(CHV_CANVAS(pipe), 0);
> - }
> -
> - i9xx_set_pipeconf(intel_crtc);
> -
> - intel_crtc->active = true;
> -
> - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
> -
> - intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
> -
> - if (IS_CHERRYVIEW(dev_priv)) {
> - chv_prepare_pll(intel_crtc, intel_crtc->config);
> - chv_enable_pll(intel_crtc, intel_crtc->config);
> - } else {
> - vlv_prepare_pll(intel_crtc, intel_crtc->config);
> - vlv_enable_pll(intel_crtc, intel_crtc->config);
> - }
> -
> - intel_encoders_pre_enable(crtc, pipe_config, old_state);
> -
> - i9xx_pfit_enable(intel_crtc);
> -
> - intel_color_load_luts(&pipe_config->base);
> -
> - intel_update_watermarks(intel_crtc);
> - intel_enable_pipe(intel_crtc);
> -
> - assert_vblank_disabled(crtc);
> - drm_crtc_vblank_on(crtc);
> -
> - intel_encoders_enable(crtc, pipe_config, old_state);
> -}
> -
> -static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
> -{
> - struct drm_device *dev = crtc->base.dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> -
> - I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
> - I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
> -}
> -
> -static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
> - struct drm_atomic_state *old_state)
> -{
> - struct drm_crtc *crtc = pipe_config->base.crtc;
> - struct drm_device *dev = crtc->dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> - enum pipe pipe = intel_crtc->pipe;
> -
> - if (WARN_ON(intel_crtc->active))
> - return;
> -
> - i9xx_set_pll_dividers(intel_crtc);
> -
> - if (intel_crtc_has_dp_encoder(intel_crtc->config))
> - intel_dp_set_m_n(intel_crtc, M1_N1);
> -
> - intel_set_pipe_timings(intel_crtc);
> - intel_set_pipe_src_size(intel_crtc);
> -
> - i9xx_set_pipeconf(intel_crtc);
> -
> - intel_crtc->active = true;
> -
> - if (!IS_GEN2(dev_priv))
> - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
> -
> - intel_encoders_pre_enable(crtc, pipe_config, old_state);
> -
> - i9xx_enable_pll(intel_crtc);
> -
> - i9xx_pfit_enable(intel_crtc);
> -
> - intel_color_load_luts(&pipe_config->base);
> -
> - intel_update_watermarks(intel_crtc);
> - intel_enable_pipe(intel_crtc);
> -
> - assert_vblank_disabled(crtc);
> - drm_crtc_vblank_on(crtc);
> -
> - intel_encoders_enable(crtc, pipe_config, old_state);
> -}
> -
> -static void i9xx_pfit_disable(struct intel_crtc *crtc)
> -{
> - struct drm_device *dev = crtc->base.dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> -
> - if (!crtc->config->gmch_pfit.control)
> - return;
> -
> - assert_pipe_disabled(dev_priv, crtc->pipe);
> -
> - DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
> - I915_READ(PFIT_CONTROL));
> - I915_WRITE(PFIT_CONTROL, 0);
> -}
> -
> -static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
> - struct drm_atomic_state *old_state)
> -{
> - struct drm_crtc *crtc = old_crtc_state->base.crtc;
> - struct drm_device *dev = crtc->dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> - int pipe = intel_crtc->pipe;
> -
> - /*
> - * On gen2 planes are double buffered but the pipe isn't, so we must
> - * wait for planes to fully turn off before disabling the pipe.
> - */
> - if (IS_GEN2(dev_priv))
> - intel_wait_for_vblank(dev_priv, pipe);
> -
> - intel_encoders_disable(crtc, old_crtc_state, old_state);
> -
> - drm_crtc_vblank_off(crtc);
> - assert_vblank_disabled(crtc);
> -
> - intel_disable_pipe(intel_crtc);
> -
> - i9xx_pfit_disable(intel_crtc);
> -
> - intel_encoders_post_disable(crtc, old_crtc_state, old_state);
> -
> - if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
> - if (IS_CHERRYVIEW(dev_priv))
> - chv_disable_pll(dev_priv, pipe);
> - else if (IS_VALLEYVIEW(dev_priv))
> - vlv_disable_pll(dev_priv, pipe);
> - else
> - i9xx_disable_pll(intel_crtc);
> - }
> -
> - intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
> -
> - if (!IS_GEN2(dev_priv))
> - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> -}
> -
> -static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
> -{
> - struct intel_encoder *encoder;
> - struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> - struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> - enum intel_display_power_domain domain;
> - unsigned long domains;
> - struct drm_atomic_state *state;
> - struct intel_crtc_state *crtc_state;
> - int ret;
> -
> - if (!intel_crtc->active)
> - return;
> -
> - if (to_intel_plane_state(crtc->primary->state)->base.visible) {
> - WARN_ON(intel_crtc->flip_work);
> -
> - intel_pre_disable_primary_noatomic(crtc);
> -
> - intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc-
> >primary));
> - to_intel_plane_state(crtc->primary->state)->base.visible =
> false;
> - }
> -
> - state = drm_atomic_state_alloc(crtc->dev);
> - state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
> -
> - /* Everything's already locked, -EDEADLK can't happen. */
> - crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
> - ret = drm_atomic_add_affected_connectors(state, crtc);
> -
> - WARN_ON(IS_ERR(crtc_state) || ret);
> -
> - dev_priv->display.crtc_disable(crtc_state, state);
> -
> - drm_atomic_state_put(state);
> -
> - DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now
> disabled\n",
> - crtc->base.id, crtc->name);
> + DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now
> disabled\n",
> + crtc->base.id, crtc->name);
>
> WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0);
> crtc->state->active = false;
> @@ -7124,543 +6182,121 @@ static int ironlake_fdi_compute_config(struct
> intel_crtc *intel_crtc,
> goto retry;
> }
>
> - if (needs_recompute)
> - return RETRY;
> -
> - return ret;
> -}
> -
> -static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
> - struct intel_crtc_state *pipe_config)
> -{
> - if (pipe_config->pipe_bpp > 24)
> - return false;
> -
> - /* HSW can handle pixel rate up to cdclk? */
> - if (IS_HASWELL(dev_priv))
> - return true;
> -
> - /*
> - * We compare against max which means we must take
> - * the increased cdclk requirement into account when
> - * calculating the new cdclk.
> - *
> - * Should measure whether using a lower cdclk w/o IPS
> - */
> - return pipe_config->pixel_rate <=
> - dev_priv->max_cdclk_freq * 95 / 100;
> -}
> -
> -static void hsw_compute_ips_config(struct intel_crtc *crtc,
> - struct intel_crtc_state *pipe_config)
> -{
> - struct drm_device *dev = crtc->base.dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> -
> - pipe_config->ips_enabled = i915.enable_ips &&
> - hsw_crtc_supports_ips(crtc) &&
> - pipe_config_supports_ips(dev_priv, pipe_config);
> -}
> -
> -static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
> -{
> - const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -
> - /* GDG double wide on either pipe, otherwise pipe A only */
> - return INTEL_INFO(dev_priv)->gen < 4 &&
> - (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
> -}
> -
> -static void intel_crtc_compute_pixel_rate(struct intel_crtc_state
> *crtc_state)
> -{
> - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc-
> >dev);
> -
> - if (HAS_GMCH_DISPLAY(dev_priv))
> - /* FIXME calculate proper pipe pixel rate GMCH pfit */
> - crtc_state->pixel_rate =
> - crtc_state->base.adjusted_mode.crtc_clock;
> - else
> - crtc_state->pixel_rate =
> - ilk_pipe_pixel_rate(crtc_state);
> -}
> -
> -static int intel_crtc_compute_config(struct intel_crtc *crtc,
> - struct intel_crtc_state *pipe_config)
> -{
> - struct drm_device *dev = crtc->base.dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - const struct drm_display_mode *adjusted_mode = &pipe_config-
> >base.adjusted_mode;
> - int clock_limit = dev_priv->max_dotclk_freq;
> -
> - if (INTEL_GEN(dev_priv) < 4) {
> - clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
> -
> - /*
> - * Enable double wide mode when the dot clock
> - * is > 90% of the (display) core speed.
> - */
> - if (intel_crtc_supports_double_wide(crtc) &&
> - adjusted_mode->crtc_clock > clock_limit) {
> - clock_limit = dev_priv->max_dotclk_freq;
> - pipe_config->double_wide = true;
> - }
> - }
> -
> - if (adjusted_mode->crtc_clock > clock_limit) {
> - DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max:
> %d kHz, double wide: %s)\n",
> - adjusted_mode->crtc_clock, clock_limit,
> - yesno(pipe_config->double_wide));
> - return -EINVAL;
> - }
> -
> - /*
> - * Pipe horizontal size must be even in:
> - * - DVO ganged mode
> - * - LVDS dual channel mode
> - * - Double wide pipe
> - */
> - if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
> - intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
> - pipe_config->pipe_src_w &= ~1;
> -
> - /* Cantiga+ cannot handle modes with a hsync front porch of 0.
> - * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
> - */
> - if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
> - adjusted_mode->crtc_hsync_start == adjusted_mode-
> >crtc_hdisplay)
> - return -EINVAL;
> -
> - intel_crtc_compute_pixel_rate(pipe_config);
> -
> - if (HAS_IPS(dev_priv))
> - hsw_compute_ips_config(crtc, pipe_config);
> -
> - if (pipe_config->has_pch_encoder)
> - return ironlake_fdi_compute_config(crtc, pipe_config);
> -
> - return 0;
> -}
> -
> -static int skylake_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - u32 cdctl;
> -
> - skl_dpll0_update(dev_priv);
> -
> - if (dev_priv->cdclk_pll.vco == 0)
> - return dev_priv->cdclk_pll.ref;
> -
> - cdctl = I915_READ(CDCLK_CTL);
> -
> - if (dev_priv->cdclk_pll.vco == 8640000) {
> - switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> - case CDCLK_FREQ_450_432:
> - return 432000;
> - case CDCLK_FREQ_337_308:
> - return 308571;
> - case CDCLK_FREQ_540:
> - return 540000;
> - case CDCLK_FREQ_675_617:
> - return 617143;
> - default:
> - MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> - }
> - } else {
> - switch (cdctl & CDCLK_FREQ_SEL_MASK) {
> - case CDCLK_FREQ_450_432:
> - return 450000;
> - case CDCLK_FREQ_337_308:
> - return 337500;
> - case CDCLK_FREQ_540:
> - return 540000;
> - case CDCLK_FREQ_675_617:
> - return 675000;
> - default:
> - MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
> - }
> - }
> -
> - return dev_priv->cdclk_pll.ref;
> -}
> -
> -static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
> -{
> - u32 val;
> -
> - dev_priv->cdclk_pll.ref = 19200;
> - dev_priv->cdclk_pll.vco = 0;
> -
> - val = I915_READ(BXT_DE_PLL_ENABLE);
> - if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
> - return;
> -
> - if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
> - return;
> -
> - val = I915_READ(BXT_DE_PLL_CTL);
> - dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
> - dev_priv->cdclk_pll.ref;
> -}
> -
> -static int broxton_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - u32 divider;
> - int div, vco;
> -
> - bxt_de_pll_update(dev_priv);
> -
> - vco = dev_priv->cdclk_pll.vco;
> - if (vco == 0)
> - return dev_priv->cdclk_pll.ref;
> -
> - divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
> -
> - switch (divider) {
> - case BXT_CDCLK_CD2X_DIV_SEL_1:
> - div = 2;
> - break;
> - case BXT_CDCLK_CD2X_DIV_SEL_1_5:
> - WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
> - div = 3;
> - break;
> - case BXT_CDCLK_CD2X_DIV_SEL_2:
> - div = 4;
> - break;
> - case BXT_CDCLK_CD2X_DIV_SEL_4:
> - div = 8;
> - break;
> - default:
> - MISSING_CASE(divider);
> - return dev_priv->cdclk_pll.ref;
> - }
> -
> - return DIV_ROUND_CLOSEST(vco, div);
> -}
> -
> -static int broadwell_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - uint32_t lcpll = I915_READ(LCPLL_CTL);
> - uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> -
> - if (lcpll & LCPLL_CD_SOURCE_FCLK)
> - return 800000;
> - else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> - return 450000;
> - else if (freq == LCPLL_CLK_FREQ_450)
> - return 450000;
> - else if (freq == LCPLL_CLK_FREQ_54O_BDW)
> - return 540000;
> - else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
> - return 337500;
> - else
> - return 675000;
> -}
> -
> -static int haswell_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - uint32_t lcpll = I915_READ(LCPLL_CTL);
> - uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
> -
> - if (lcpll & LCPLL_CD_SOURCE_FCLK)
> - return 800000;
> - else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
> - return 450000;
> - else if (freq == LCPLL_CLK_FREQ_450)
> - return 450000;
> - else if (IS_HSW_ULT(dev_priv))
> - return 337500;
> - else
> - return 540000;
> -}
> -
> -static int valleyview_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
> - CCK_DISPLAY_CLOCK_CONTROL);
> -}
> -
> -static int fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - return 450000;
> -}
> -
> -static int fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - return 400000;
> -}
> -
> -static int fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - return 333333;
> -}
> -
> -static int fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - return 200000;
> -}
> -
> -static int pnv_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - struct pci_dev *pdev = dev_priv->drm.pdev;
> - u16 gcfgc = 0;
> -
> - pci_read_config_word(pdev, GCFGC, &gcfgc);
> -
> - switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> - case GC_DISPLAY_CLOCK_267_MHZ_PNV:
> - return 266667;
> - case GC_DISPLAY_CLOCK_333_MHZ_PNV:
> - return 333333;
> - case GC_DISPLAY_CLOCK_444_MHZ_PNV:
> - return 444444;
> - case GC_DISPLAY_CLOCK_200_MHZ_PNV:
> - return 200000;
> - default:
> - DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
> - case GC_DISPLAY_CLOCK_133_MHZ_PNV:
> - return 133333;
> - case GC_DISPLAY_CLOCK_167_MHZ_PNV:
> - return 166667;
> - }
> -}
> -
> -static int i915gm_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - 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;
> - else {
> - switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
> - case GC_DISPLAY_CLOCK_333_MHZ:
> - return 333333;
> - default:
> - case GC_DISPLAY_CLOCK_190_200_MHZ:
> - return 190000;
> - }
> - }
> -}
> -
> -static int fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - return 266667;
> + if (needs_recompute)
> + return RETRY;
> +
> + return ret;
> }
>
> -static int i85x_get_cdclk(struct drm_i915_private *dev_priv)
> +static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
> + struct intel_crtc_state *pipe_config)
> {
> - struct pci_dev *pdev = dev_priv->drm.pdev;
> - u16 hpllcc = 0;
> -
> - /*
> - * 852GM/852GMV only supports 133 MHz and the HPLLCC
> - * encoding is different :(
> - * FIXME is this the right way to detect 852GM/852GMV?
> - */
> - if (pdev->revision == 0x1)
> - return 133333;
> + if (pipe_config->pipe_bpp > 24)
> + return false;
>
> - pci_bus_read_config_word(pdev->bus,
> - PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
> + /* HSW can handle pixel rate up to cdclk? */
> + if (IS_HASWELL(dev_priv))
> + return true;
>
> - /* Assume that the hardware is in the high speed state. This
> - * should be the default.
> + /*
> + * We compare against max which means we must take
> + * the increased cdclk requirement into account when
> + * calculating the new cdclk.
> + *
> + * Should measure whether using a lower cdclk w/o IPS
> */
> - switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
> - case GC_CLOCK_133_200:
> - case GC_CLOCK_133_200_2:
> - case GC_CLOCK_100_200:
> - return 200000;
> - case GC_CLOCK_166_250:
> - return 250000;
> - case GC_CLOCK_100_133:
> - return 133333;
> - case GC_CLOCK_133_266:
> - case GC_CLOCK_133_266_2:
> - case GC_CLOCK_166_266:
> - return 266667;
> - }
> -
> - /* Shouldn't happen */
> - return 0;
> + return pipe_config->pixel_rate <=
> + dev_priv->max_cdclk_freq * 95 / 100;
> }
>
> -static int fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv)
> +static void hsw_compute_ips_config(struct intel_crtc *crtc,
> + struct intel_crtc_state *pipe_config)
> {
> - return 133333;
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> +
> + pipe_config->ips_enabled = i915.enable_ips &&
> + hsw_crtc_supports_ips(crtc) &&
> + pipe_config_supports_ips(dev_priv, pipe_config);
> }
>
> -static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
> +static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
> {
> - static const unsigned int blb_vco[8] = {
> - [0] = 3200000,
> - [1] = 4000000,
> - [2] = 5333333,
> - [3] = 4800000,
> - [4] = 6400000,
> - };
> - static const unsigned int pnv_vco[8] = {
> - [0] = 3200000,
> - [1] = 4000000,
> - [2] = 5333333,
> - [3] = 4800000,
> - [4] = 2666667,
> - };
> - static const unsigned int cl_vco[8] = {
> - [0] = 3200000,
> - [1] = 4000000,
> - [2] = 5333333,
> - [3] = 6400000,
> - [4] = 3333333,
> - [5] = 3566667,
> - [6] = 4266667,
> - };
> - static const unsigned int elk_vco[8] = {
> - [0] = 3200000,
> - [1] = 4000000,
> - [2] = 5333333,
> - [3] = 4800000,
> - };
> - static const unsigned int ctg_vco[8] = {
> - [0] = 3200000,
> - [1] = 4000000,
> - [2] = 5333333,
> - [3] = 6400000,
> - [4] = 2666667,
> - [5] = 4266667,
> - };
> - const unsigned int *vco_table;
> - unsigned int vco;
> - uint8_t tmp = 0;
> -
> - /* FIXME other chipsets? */
> - if (IS_GM45(dev_priv))
> - vco_table = ctg_vco;
> - else if (IS_G4X(dev_priv))
> - vco_table = elk_vco;
> - else if (IS_I965GM(dev_priv))
> - vco_table = cl_vco;
> - else if (IS_PINEVIEW(dev_priv))
> - vco_table = pnv_vco;
> - else if (IS_G33(dev_priv))
> - vco_table = blb_vco;
> - else
> - return 0;
> -
> - tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
> -
> - vco = vco_table[tmp & 0x7];
> - if (vco == 0)
> - DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
> - else
> - DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
> + const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>
> - return vco;
> + /* GDG double wide on either pipe, otherwise pipe A only */
> + return INTEL_INFO(dev_priv)->gen < 4 &&
> + (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
> }
>
> -static int gm45_get_cdclk(struct drm_i915_private *dev_priv)
> +static void intel_crtc_compute_pixel_rate(struct intel_crtc_state
> *crtc_state)
> {
> - struct pci_dev *pdev = dev_priv->drm.pdev;
> - unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
> - uint16_t tmp = 0;
> -
> - pci_read_config_word(pdev, GCFGC, &tmp);
> -
> - cdclk_sel = (tmp >> 12) & 0x1;
> + struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc-
> >dev);
>
> - switch (vco) {
> - case 2666667:
> - case 4000000:
> - case 5333333:
> - return cdclk_sel ? 333333 : 222222;
> - case 3200000:
> - return cdclk_sel ? 320000 : 228571;
> - default:
> - DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u,
> CFGC=0x%04x\n", vco, tmp);
> - return 222222;
> - }
> + if (HAS_GMCH_DISPLAY(dev_priv))
> + /* FIXME calculate proper pipe pixel rate GMCH pfit */
> + crtc_state->pixel_rate =
> + crtc_state->base.adjusted_mode.crtc_clock;
> + else
> + crtc_state->pixel_rate =
> + ilk_pipe_pixel_rate(crtc_state);
> }
>
> -static int i965gm_get_cdclk(struct drm_i915_private *dev_priv)
> +static int intel_crtc_compute_config(struct intel_crtc *crtc,
> + struct intel_crtc_state *pipe_config)
> {
> - 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);
> - uint16_t tmp = 0;
> -
> - pci_read_config_word(pdev, GCFGC, &tmp);
> -
> - cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + const struct drm_display_mode *adjusted_mode = &pipe_config-
> >base.adjusted_mode;
> + int clock_limit = dev_priv->max_dotclk_freq;
>
> - if (cdclk_sel >= ARRAY_SIZE(div_3200))
> - goto fail;
> + if (INTEL_GEN(dev_priv) < 4) {
> + clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
>
> - switch (vco) {
> - case 3200000:
> - div_table = div_3200;
> - break;
> - case 4000000:
> - div_table = div_4000;
> - break;
> - case 5333333:
> - div_table = div_5333;
> - break;
> - default:
> - goto fail;
> + /*
> + * Enable double wide mode when the dot clock
> + * is > 90% of the (display) core speed.
> + */
> + if (intel_crtc_supports_double_wide(crtc) &&
> + adjusted_mode->crtc_clock > clock_limit) {
> + clock_limit = dev_priv->max_dotclk_freq;
> + pipe_config->double_wide = true;
> + }
> }
>
> - return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> -
> -fail:
> - DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%04x\n", vco, tmp);
> - return 200000;
> -}
> -
> -static int g33_get_cdclk(struct drm_i915_private *dev_priv)
> -{
> - struct pci_dev *pdev = dev_priv->drm.pdev;
> - static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 };
> - static const uint8_t div_4000[] = { 14, 12, 10, 8, 6, 20 };
> - 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);
> - uint16_t tmp = 0;
> + if (adjusted_mode->crtc_clock > clock_limit) {
> + DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max:
> %d kHz, double wide: %s)\n",
> + adjusted_mode->crtc_clock, clock_limit,
> + yesno(pipe_config->double_wide));
> + return -EINVAL;
> + }
>
> - pci_read_config_word(pdev, GCFGC, &tmp);
> + /*
> + * Pipe horizontal size must be even in:
> + * - DVO ganged mode
> + * - LVDS dual channel mode
> + * - Double wide pipe
> + */
> + if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
> + intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
> + pipe_config->pipe_src_w &= ~1;
>
> - cdclk_sel = (tmp >> 4) & 0x7;
> + /* Cantiga+ cannot handle modes with a hsync front porch of 0.
> + * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
> + */
> + if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
> + adjusted_mode->crtc_hsync_start == adjusted_mode-
> >crtc_hdisplay)
> + return -EINVAL;
>
> - if (cdclk_sel >= ARRAY_SIZE(div_3200))
> - goto fail;
> + intel_crtc_compute_pixel_rate(pipe_config);
>
> - switch (vco) {
> - case 3200000:
> - div_table = div_3200;
> - break;
> - case 4000000:
> - div_table = div_4000;
> - break;
> - case 4800000:
> - div_table = div_4800;
> - break;
> - case 5333333:
> - div_table = div_5333;
> - break;
> - default:
> - goto fail;
> - }
> + if (HAS_IPS(dev_priv))
> + hsw_compute_ips_config(crtc, pipe_config);
>
> - return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
> + if (pipe_config->has_pch_encoder)
> + return ironlake_fdi_compute_config(crtc, pipe_config);
>
> -fail:
> - DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz,
> CFGC=0x%08x\n", vco, tmp);
> - return 190476;
> + return 0;
> }
>
> static void
> @@ -10225,245 +8861,6 @@ void hsw_disable_pc8(struct drm_i915_private
> *dev_priv)
> }
> }
>
> -static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> - struct drm_device *dev = old_state->dev;
> - struct intel_atomic_state *old_intel_state =
> - to_intel_atomic_state(old_state);
> - unsigned int req_cdclk = old_intel_state->dev_cdclk;
> -
> - bxt_set_cdclk(to_i915(dev), req_cdclk);
> -}
> -
> -static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state
> *crtc_state,
> - int pixel_rate)
> -{
> - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc-
> >dev);
> -
> - /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
> - if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
> - pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
> -
> - /* BSpec says "Do not use DisplayPort with CDCLK less than
> - * 432 MHz, audio enabled, port width x4, and link rate
> - * HBR2 (5.4 GHz), or else there may be audio corruption or
> - * screen corruption."
> - */
> - if (intel_crtc_has_dp_encoder(crtc_state) &&
> - crtc_state->has_audio &&
> - crtc_state->port_clock >= 540000 &&
> - crtc_state->lane_count == 4)
> - pixel_rate = max(432000, pixel_rate);
> -
> - return pixel_rate;
> -}
> -
> -/* compute the max rate for new configuration */
> -static int intel_max_pixel_rate(struct drm_atomic_state *state)
> -{
> - struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> - struct drm_i915_private *dev_priv = to_i915(state->dev);
> - struct drm_crtc *crtc;
> - struct drm_crtc_state *cstate;
> - struct intel_crtc_state *crtc_state;
> - unsigned max_pixel_rate = 0, i;
> - enum pipe pipe;
> -
> - memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
> - sizeof(intel_state->min_pixclk));
> -
> - for_each_crtc_in_state(state, crtc, cstate, i) {
> - int pixel_rate;
> -
> - crtc_state = to_intel_crtc_state(cstate);
> - if (!crtc_state->base.enable) {
> - intel_state->min_pixclk[i] = 0;
> - continue;
> - }
> -
> - pixel_rate = crtc_state->pixel_rate;
> -
> - if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
> - pixel_rate =
> bdw_adjust_min_pipe_pixel_rate(crtc_state,
> - pixel_rat
> e);
> -
> - intel_state->min_pixclk[i] = pixel_rate;
> - }
> -
> - for_each_pipe(dev_priv, pipe)
> - max_pixel_rate = max(intel_state->min_pixclk[pipe],
> max_pixel_rate);
> -
> - return max_pixel_rate;
> -}
> -
> -static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
> -{
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - uint32_t val, data;
> - int ret;
> -
> - 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;
> -
> - mutex_lock(&dev_priv->rps.hw_lock);
> - ret = sandybridge_pcode_write(dev_priv,
> - BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ,
> 0x0);
> - mutex_unlock(&dev_priv->rps.hw_lock);
> - if (ret) {
> - DRM_ERROR("failed to inform pcode about cdclk change\n");
> - return;
> - }
> -
> - val = I915_READ(LCPLL_CTL);
> - val |= LCPLL_CD_SOURCE_FCLK;
> - I915_WRITE(LCPLL_CTL, val);
> -
> - if (wait_for_us(I915_READ(LCPLL_CTL) &
> - LCPLL_CD_SOURCE_FCLK_DONE, 1))
> - DRM_ERROR("Switching to FCLK failed\n");
> -
> - val = I915_READ(LCPLL_CTL);
> - val &= ~LCPLL_CLK_FREQ_MASK;
> -
> - switch (cdclk) {
> - case 450000:
> - val |= LCPLL_CLK_FREQ_450;
> - data = 0;
> - break;
> - case 540000:
> - val |= LCPLL_CLK_FREQ_54O_BDW;
> - data = 1;
> - break;
> - case 337500:
> - val |= LCPLL_CLK_FREQ_337_5_BDW;
> - data = 2;
> - break;
> - case 675000:
> - val |= LCPLL_CLK_FREQ_675_BDW;
> - data = 3;
> - break;
> - default:
> - WARN(1, "invalid cdclk frequency\n");
> - return;
> - }
> -
> - I915_WRITE(LCPLL_CTL, val);
> -
> - val = I915_READ(LCPLL_CTL);
> - val &= ~LCPLL_CD_SOURCE_FCLK;
> - I915_WRITE(LCPLL_CTL, val);
> -
> - if (wait_for_us((I915_READ(LCPLL_CTL) &
> - LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
> - DRM_ERROR("Switching back to LCPLL failed\n");
> -
> - mutex_lock(&dev_priv->rps.hw_lock);
> - sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
> - mutex_unlock(&dev_priv->rps.hw_lock);
> -
> - I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
> -
> - intel_update_cdclk(dev_priv);
> -
> - WARN(cdclk != dev_priv->cdclk_freq,
> - "cdclk requested %d kHz but got %d kHz\n",
> - cdclk, dev_priv->cdclk_freq);
> -}
> -
> -static int broadwell_calc_cdclk(int max_pixclk)
> -{
> - if (max_pixclk > 540000)
> - return 675000;
> - else if (max_pixclk > 450000)
> - return 540000;
> - else if (max_pixclk > 337500)
> - return 450000;
> - else
> - return 337500;
> -}
> -
> -static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> - struct drm_i915_private *dev_priv = to_i915(state->dev);
> - struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> - int max_pixclk = intel_max_pixel_rate(state);
> - int cdclk;
> -
> - /*
> - * FIXME should also account for plane ratio
> - * once 64bpp pixel formats are supported.
> - */
> - cdclk = broadwell_calc_cdclk(max_pixclk);
> -
> - if (cdclk > dev_priv->max_cdclk_freq) {
> - DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d
> kHz)\n",
> - cdclk, dev_priv->max_cdclk_freq);
> - return -EINVAL;
> - }
> -
> - intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> - if (!intel_state->active_crtcs)
> - intel_state->dev_cdclk = broadwell_calc_cdclk(0);
> -
> - return 0;
> -}
> -
> -static void broadwell_modeset_commit_cdclk(struct drm_atomic_state
> *old_state)
> -{
> - struct drm_device *dev = old_state->dev;
> - struct intel_atomic_state *old_intel_state =
> - to_intel_atomic_state(old_state);
> - unsigned req_cdclk = old_intel_state->dev_cdclk;
> -
> - broadwell_set_cdclk(dev, req_cdclk);
> -}
> -
> -static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
> -{
> - struct intel_atomic_state *intel_state =
> to_intel_atomic_state(state);
> - struct drm_i915_private *dev_priv = to_i915(state->dev);
> - const int max_pixclk = intel_max_pixel_rate(state);
> - int vco = intel_state->cdclk_pll_vco;
> - int cdclk;
> -
> - /*
> - * FIXME should also account for plane ratio
> - * once 64bpp pixel formats are supported.
> - */
> - cdclk = skl_calc_cdclk(max_pixclk, vco);
> -
> - /*
> - * 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;
> - }
> -
> - intel_state->cdclk = intel_state->dev_cdclk = cdclk;
> - if (!intel_state->active_crtcs)
> - intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
> -
> - return 0;
> -}
> -
> -static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> -{
> - struct drm_i915_private *dev_priv = to_i915(old_state->dev);
> - struct intel_atomic_state *intel_state =
> to_intel_atomic_state(old_state);
> - unsigned int req_cdclk = intel_state->dev_cdclk;
> - unsigned int req_vco = intel_state->cdclk_pll_vco;
> -
> - skl_set_cdclk(dev_priv, req_cdclk, req_vco);
> -}
> -
> static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
> struct intel_crtc_state *crtc_state)
> {
> @@ -16019,6 +14416,8 @@ static const struct drm_mode_config_funcs
> intel_mode_funcs = {
> */
> void intel_init_display_hooks(struct drm_i915_private *dev_priv)
> {
> + intel_init_cdclk_hooks(dev_priv);
> +
> if (INTEL_INFO(dev_priv)->gen >= 9) {
> dev_priv->display.get_pipe_config = haswell_get_pipe_config;
> dev_priv->display.get_initial_plane_config =
> @@ -16087,52 +14486,6 @@ void intel_init_display_hooks(struct drm_i915_private
> *dev_priv)
> dev_priv->display.crtc_disable = i9xx_crtc_disable;
> }
>
> - /* Returns the core display clock speed */
> - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
> - dev_priv->display.get_cdclk = skylake_get_cdclk;
> - else if (IS_GEN9_LP(dev_priv))
> - dev_priv->display.get_cdclk = broxton_get_cdclk;
> - else if (IS_BROADWELL(dev_priv))
> - dev_priv->display.get_cdclk = broadwell_get_cdclk;
> - else if (IS_HASWELL(dev_priv))
> - dev_priv->display.get_cdclk = haswell_get_cdclk;
> - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> - dev_priv->display.get_cdclk = valleyview_get_cdclk;
> - else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
> - dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> - else if (IS_GEN5(dev_priv))
> - dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
> - else if (IS_GM45(dev_priv))
> - dev_priv->display.get_cdclk = gm45_get_cdclk;
> - else if (IS_G4X(dev_priv))
> - dev_priv->display.get_cdclk = g33_get_cdclk;
> - else if (IS_I965GM(dev_priv))
> - dev_priv->display.get_cdclk = i965gm_get_cdclk;
> - else if (IS_I965G(dev_priv))
> - dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> - else if (IS_PINEVIEW(dev_priv))
> - dev_priv->display.get_cdclk = pnv_get_cdclk;
> - else if (IS_G33(dev_priv))
> - dev_priv->display.get_cdclk = g33_get_cdclk;
> - else if (IS_I945GM(dev_priv))
> - dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> - else if (IS_I945G(dev_priv))
> - dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
> - else if (IS_I915GM(dev_priv))
> - dev_priv->display.get_cdclk = i915gm_get_cdclk;
> - else if (IS_I915G(dev_priv))
> - dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
> - else if (IS_I865G(dev_priv))
> - dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
> - else if (IS_I85X(dev_priv))
> - dev_priv->display.get_cdclk = i85x_get_cdclk;
> - else if (IS_I845G(dev_priv))
> - dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
> - else { /* 830 */
> - WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz
> CDCLK\n");
> - dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
> - }
> -
> if (IS_GEN5(dev_priv)) {
> dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
> } else if (IS_GEN6(dev_priv)) {
> @@ -16144,28 +14497,6 @@ void intel_init_display_hooks(struct drm_i915_private
> *dev_priv)
> dev_priv->display.fdi_link_train = hsw_fdi_link_train;
> }
>
> - if (IS_BROADWELL(dev_priv)) {
> - dev_priv->display.modeset_commit_cdclk =
> - broadwell_modeset_commit_cdclk;
> - dev_priv->display.modeset_calc_cdclk =
> - broadwell_modeset_calc_cdclk;
> - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> - dev_priv->display.modeset_commit_cdclk =
> - valleyview_modeset_commit_cdclk;
> - dev_priv->display.modeset_calc_cdclk =
> - valleyview_modeset_calc_cdclk;
> - } else if (IS_GEN9_LP(dev_priv)) {
> - dev_priv->display.modeset_commit_cdclk =
> - bxt_modeset_commit_cdclk;
> - dev_priv->display.modeset_calc_cdclk =
> - bxt_modeset_calc_cdclk;
> - } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
> - dev_priv->display.modeset_commit_cdclk =
> - skl_modeset_commit_cdclk;
> - dev_priv->display.modeset_calc_cdclk =
> - skl_modeset_calc_cdclk;
> - }
> -
> if (dev_priv->info.gen >= 9)
> dev_priv->display.update_crtcs = skl_update_crtcs;
> else
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index 3969e786d566..8d93b7bda3ff 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1220,12 +1220,19 @@ void intel_audio_codec_disable(struct intel_encoder
> *encoder);
> void i915_audio_component_init(struct drm_i915_private *dev_priv);
> void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
>
> +/* intel_cdclk.c */
> +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);
> +
> /* intel_display.c */
> enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
> -void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco);
> void intel_update_rawclk(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,
> + const char *name, u32 reg);
> void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv);
> void lpt_disable_iclkip(struct drm_i915_private *dev_priv);
> extern const struct drm_plane_funcs intel_plane_funcs;
More information about the Intel-gfx
mailing list