On Mon, 2016-12-19 at 19:28 +0200, ville.syrjala@xxxxxxxxxxxxxxx wrote: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > 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@xxxxxxxxx> > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > 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; _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx