cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_pch_refclk.c (17725B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright © 2021 Intel Corporation
      4 */
      5
      6#include "intel_de.h"
      7#include "intel_display_types.h"
      8#include "intel_panel.h"
      9#include "intel_pch_refclk.h"
     10#include "intel_sbi.h"
     11
     12static void lpt_fdi_reset_mphy(struct drm_i915_private *dev_priv)
     13{
     14	u32 tmp;
     15
     16	tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2);
     17	tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
     18	intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp);
     19
     20	if (wait_for_us(intel_de_read(dev_priv, SOUTH_CHICKEN2) &
     21			FDI_MPHY_IOSFSB_RESET_STATUS, 100))
     22		drm_err(&dev_priv->drm, "FDI mPHY reset assert timeout\n");
     23
     24	tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2);
     25	tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL;
     26	intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp);
     27
     28	if (wait_for_us((intel_de_read(dev_priv, SOUTH_CHICKEN2) &
     29			 FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100))
     30		drm_err(&dev_priv->drm, "FDI mPHY reset de-assert timeout\n");
     31}
     32
     33/* WaMPhyProgramming:hsw */
     34static void lpt_fdi_program_mphy(struct drm_i915_private *dev_priv)
     35{
     36	u32 tmp;
     37
     38	lpt_fdi_reset_mphy(dev_priv);
     39
     40	tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY);
     41	tmp &= ~(0xFF << 24);
     42	tmp |= (0x12 << 24);
     43	intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY);
     44
     45	tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY);
     46	tmp |= (1 << 11);
     47	intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY);
     48
     49	tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY);
     50	tmp |= (1 << 11);
     51	intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY);
     52
     53	tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY);
     54	tmp |= (1 << 24) | (1 << 21) | (1 << 18);
     55	intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY);
     56
     57	tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY);
     58	tmp |= (1 << 24) | (1 << 21) | (1 << 18);
     59	intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY);
     60
     61	tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY);
     62	tmp &= ~(7 << 13);
     63	tmp |= (5 << 13);
     64	intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY);
     65
     66	tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY);
     67	tmp &= ~(7 << 13);
     68	tmp |= (5 << 13);
     69	intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY);
     70
     71	tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY);
     72	tmp &= ~0xFF;
     73	tmp |= 0x1C;
     74	intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY);
     75
     76	tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY);
     77	tmp &= ~0xFF;
     78	tmp |= 0x1C;
     79	intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY);
     80
     81	tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY);
     82	tmp &= ~(0xFF << 16);
     83	tmp |= (0x1C << 16);
     84	intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY);
     85
     86	tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY);
     87	tmp &= ~(0xFF << 16);
     88	tmp |= (0x1C << 16);
     89	intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY);
     90
     91	tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY);
     92	tmp |= (1 << 27);
     93	intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY);
     94
     95	tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY);
     96	tmp |= (1 << 27);
     97	intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY);
     98
     99	tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY);
    100	tmp &= ~(0xF << 28);
    101	tmp |= (4 << 28);
    102	intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY);
    103
    104	tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY);
    105	tmp &= ~(0xF << 28);
    106	tmp |= (4 << 28);
    107	intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY);
    108}
    109
    110void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
    111{
    112	u32 temp;
    113
    114	intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_GATE);
    115
    116	mutex_lock(&dev_priv->sb_lock);
    117
    118	temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
    119	temp |= SBI_SSCCTL_DISABLE;
    120	intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
    121
    122	mutex_unlock(&dev_priv->sb_lock);
    123}
    124
    125/* Program iCLKIP clock to the desired frequency */
    126void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
    127{
    128	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
    129	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
    130	int clock = crtc_state->hw.adjusted_mode.crtc_clock;
    131	u32 divsel, phaseinc, auxdiv, phasedir = 0;
    132	u32 temp;
    133
    134	lpt_disable_iclkip(dev_priv);
    135
    136	/* The iCLK virtual clock root frequency is in MHz,
    137	 * but the adjusted_mode->crtc_clock in KHz. To get the
    138	 * divisors, it is necessary to divide one by another, so we
    139	 * convert the virtual clock precision to KHz here for higher
    140	 * precision.
    141	 */
    142	for (auxdiv = 0; auxdiv < 2; auxdiv++) {
    143		u32 iclk_virtual_root_freq = 172800 * 1000;
    144		u32 iclk_pi_range = 64;
    145		u32 desired_divisor;
    146
    147		desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq,
    148						    clock << auxdiv);
    149		divsel = (desired_divisor / iclk_pi_range) - 2;
    150		phaseinc = desired_divisor % iclk_pi_range;
    151
    152		/*
    153		 * Near 20MHz is a corner case which is
    154		 * out of range for the 7-bit divisor
    155		 */
    156		if (divsel <= 0x7f)
    157			break;
    158	}
    159
    160	/* This should not happen with any sane values */
    161	drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIVSEL(divsel) &
    162		    ~SBI_SSCDIVINTPHASE_DIVSEL_MASK);
    163	drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIR(phasedir) &
    164		    ~SBI_SSCDIVINTPHASE_INCVAL_MASK);
    165
    166	drm_dbg_kms(&dev_priv->drm,
    167		    "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
    168		    clock, auxdiv, divsel, phasedir, phaseinc);
    169
    170	mutex_lock(&dev_priv->sb_lock);
    171
    172	/* Program SSCDIVINTPHASE6 */
    173	temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
    174	temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
    175	temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel);
    176	temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK;
    177	temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc);
    178	temp |= SBI_SSCDIVINTPHASE_DIR(phasedir);
    179	temp |= SBI_SSCDIVINTPHASE_PROPAGATE;
    180	intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK);
    181
    182	/* Program SSCAUXDIV */
    183	temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
    184	temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
    185	temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv);
    186	intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK);
    187
    188	/* Enable modulator and associated divider */
    189	temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
    190	temp &= ~SBI_SSCCTL_DISABLE;
    191	intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
    192
    193	mutex_unlock(&dev_priv->sb_lock);
    194
    195	/* Wait for initialization time */
    196	udelay(24);
    197
    198	intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_UNGATE);
    199}
    200
    201int lpt_get_iclkip(struct drm_i915_private *dev_priv)
    202{
    203	u32 divsel, phaseinc, auxdiv;
    204	u32 iclk_virtual_root_freq = 172800 * 1000;
    205	u32 iclk_pi_range = 64;
    206	u32 desired_divisor;
    207	u32 temp;
    208
    209	if ((intel_de_read(dev_priv, PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0)
    210		return 0;
    211
    212	mutex_lock(&dev_priv->sb_lock);
    213
    214	temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
    215	if (temp & SBI_SSCCTL_DISABLE) {
    216		mutex_unlock(&dev_priv->sb_lock);
    217		return 0;
    218	}
    219
    220	temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
    221	divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >>
    222		SBI_SSCDIVINTPHASE_DIVSEL_SHIFT;
    223	phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >>
    224		SBI_SSCDIVINTPHASE_INCVAL_SHIFT;
    225
    226	temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
    227	auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >>
    228		SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT;
    229
    230	mutex_unlock(&dev_priv->sb_lock);
    231
    232	desired_divisor = (divsel + 2) * iclk_pi_range + phaseinc;
    233
    234	return DIV_ROUND_CLOSEST(iclk_virtual_root_freq,
    235				 desired_divisor << auxdiv);
    236}
    237
    238/* Implements 3 different sequences from BSpec chapter "Display iCLK
    239 * Programming" based on the parameters passed:
    240 * - Sequence to enable CLKOUT_DP
    241 * - Sequence to enable CLKOUT_DP without spread
    242 * - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O
    243 */
    244static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
    245				 bool with_spread, bool with_fdi)
    246{
    247	u32 reg, tmp;
    248
    249	if (drm_WARN(&dev_priv->drm, with_fdi && !with_spread,
    250		     "FDI requires downspread\n"))
    251		with_spread = true;
    252	if (drm_WARN(&dev_priv->drm, HAS_PCH_LPT_LP(dev_priv) &&
    253		     with_fdi, "LP PCH doesn't have FDI\n"))
    254		with_fdi = false;
    255
    256	mutex_lock(&dev_priv->sb_lock);
    257
    258	tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
    259	tmp &= ~SBI_SSCCTL_DISABLE;
    260	tmp |= SBI_SSCCTL_PATHALT;
    261	intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
    262
    263	udelay(24);
    264
    265	if (with_spread) {
    266		tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
    267		tmp &= ~SBI_SSCCTL_PATHALT;
    268		intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
    269
    270		if (with_fdi)
    271			lpt_fdi_program_mphy(dev_priv);
    272	}
    273
    274	reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
    275	tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
    276	tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
    277	intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
    278
    279	mutex_unlock(&dev_priv->sb_lock);
    280}
    281
    282/* Sequence to disable CLKOUT_DP */
    283void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
    284{
    285	u32 reg, tmp;
    286
    287	mutex_lock(&dev_priv->sb_lock);
    288
    289	reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
    290	tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
    291	tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE;
    292	intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
    293
    294	tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
    295	if (!(tmp & SBI_SSCCTL_DISABLE)) {
    296		if (!(tmp & SBI_SSCCTL_PATHALT)) {
    297			tmp |= SBI_SSCCTL_PATHALT;
    298			intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
    299			udelay(32);
    300		}
    301		tmp |= SBI_SSCCTL_DISABLE;
    302		intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
    303	}
    304
    305	mutex_unlock(&dev_priv->sb_lock);
    306}
    307
    308#define BEND_IDX(steps) ((50 + (steps)) / 5)
    309
    310static const u16 sscdivintphase[] = {
    311	[BEND_IDX( 50)] = 0x3B23,
    312	[BEND_IDX( 45)] = 0x3B23,
    313	[BEND_IDX( 40)] = 0x3C23,
    314	[BEND_IDX( 35)] = 0x3C23,
    315	[BEND_IDX( 30)] = 0x3D23,
    316	[BEND_IDX( 25)] = 0x3D23,
    317	[BEND_IDX( 20)] = 0x3E23,
    318	[BEND_IDX( 15)] = 0x3E23,
    319	[BEND_IDX( 10)] = 0x3F23,
    320	[BEND_IDX(  5)] = 0x3F23,
    321	[BEND_IDX(  0)] = 0x0025,
    322	[BEND_IDX( -5)] = 0x0025,
    323	[BEND_IDX(-10)] = 0x0125,
    324	[BEND_IDX(-15)] = 0x0125,
    325	[BEND_IDX(-20)] = 0x0225,
    326	[BEND_IDX(-25)] = 0x0225,
    327	[BEND_IDX(-30)] = 0x0325,
    328	[BEND_IDX(-35)] = 0x0325,
    329	[BEND_IDX(-40)] = 0x0425,
    330	[BEND_IDX(-45)] = 0x0425,
    331	[BEND_IDX(-50)] = 0x0525,
    332};
    333
    334/*
    335 * Bend CLKOUT_DP
    336 * steps -50 to 50 inclusive, in steps of 5
    337 * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz)
    338 * change in clock period = -(steps / 10) * 5.787 ps
    339 */
    340static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
    341{
    342	u32 tmp;
    343	int idx = BEND_IDX(steps);
    344
    345	if (drm_WARN_ON(&dev_priv->drm, steps % 5 != 0))
    346		return;
    347
    348	if (drm_WARN_ON(&dev_priv->drm, idx >= ARRAY_SIZE(sscdivintphase)))
    349		return;
    350
    351	mutex_lock(&dev_priv->sb_lock);
    352
    353	if (steps % 10 != 0)
    354		tmp = 0xAAAAAAAB;
    355	else
    356		tmp = 0x00000000;
    357	intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK);
    358
    359	tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK);
    360	tmp &= 0xffff0000;
    361	tmp |= sscdivintphase[idx];
    362	intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
    363
    364	mutex_unlock(&dev_priv->sb_lock);
    365}
    366
    367#undef BEND_IDX
    368
    369static bool spll_uses_pch_ssc(struct drm_i915_private *dev_priv)
    370{
    371	u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP);
    372	u32 ctl = intel_de_read(dev_priv, SPLL_CTL);
    373
    374	if ((ctl & SPLL_PLL_ENABLE) == 0)
    375		return false;
    376
    377	if ((ctl & SPLL_REF_MASK) == SPLL_REF_MUXED_SSC &&
    378	    (fuse_strap & HSW_CPU_SSC_ENABLE) == 0)
    379		return true;
    380
    381	if (IS_BROADWELL(dev_priv) &&
    382	    (ctl & SPLL_REF_MASK) == SPLL_REF_PCH_SSC_BDW)
    383		return true;
    384
    385	return false;
    386}
    387
    388static bool wrpll_uses_pch_ssc(struct drm_i915_private *dev_priv,
    389			       enum intel_dpll_id id)
    390{
    391	u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP);
    392	u32 ctl = intel_de_read(dev_priv, WRPLL_CTL(id));
    393
    394	if ((ctl & WRPLL_PLL_ENABLE) == 0)
    395		return false;
    396
    397	if ((ctl & WRPLL_REF_MASK) == WRPLL_REF_PCH_SSC)
    398		return true;
    399
    400	if ((IS_BROADWELL(dev_priv) || IS_HSW_ULT(dev_priv)) &&
    401	    (ctl & WRPLL_REF_MASK) == WRPLL_REF_MUXED_SSC_BDW &&
    402	    (fuse_strap & HSW_CPU_SSC_ENABLE) == 0)
    403		return true;
    404
    405	return false;
    406}
    407
    408static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv)
    409{
    410	struct intel_encoder *encoder;
    411	bool has_fdi = false;
    412
    413	for_each_intel_encoder(&dev_priv->drm, encoder) {
    414		switch (encoder->type) {
    415		case INTEL_OUTPUT_ANALOG:
    416			has_fdi = true;
    417			break;
    418		default:
    419			break;
    420		}
    421	}
    422
    423	/*
    424	 * The BIOS may have decided to use the PCH SSC
    425	 * reference so we must not disable it until the
    426	 * relevant PLLs have stopped relying on it. We'll
    427	 * just leave the PCH SSC reference enabled in case
    428	 * any active PLL is using it. It will get disabled
    429	 * after runtime suspend if we don't have FDI.
    430	 *
    431	 * TODO: Move the whole reference clock handling
    432	 * to the modeset sequence proper so that we can
    433	 * actually enable/disable/reconfigure these things
    434	 * safely. To do that we need to introduce a real
    435	 * clock hierarchy. That would also allow us to do
    436	 * clock bending finally.
    437	 */
    438	dev_priv->pch_ssc_use = 0;
    439
    440	if (spll_uses_pch_ssc(dev_priv)) {
    441		drm_dbg_kms(&dev_priv->drm, "SPLL using PCH SSC\n");
    442		dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL);
    443	}
    444
    445	if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) {
    446		drm_dbg_kms(&dev_priv->drm, "WRPLL1 using PCH SSC\n");
    447		dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1);
    448	}
    449
    450	if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) {
    451		drm_dbg_kms(&dev_priv->drm, "WRPLL2 using PCH SSC\n");
    452		dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2);
    453	}
    454
    455	if (dev_priv->pch_ssc_use)
    456		return;
    457
    458	if (has_fdi) {
    459		lpt_bend_clkout_dp(dev_priv, 0);
    460		lpt_enable_clkout_dp(dev_priv, true, true);
    461	} else {
    462		lpt_disable_clkout_dp(dev_priv);
    463	}
    464}
    465
    466static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
    467{
    468	struct intel_encoder *encoder;
    469	int i;
    470	u32 val, final;
    471	bool has_lvds = false;
    472	bool has_cpu_edp = false;
    473	bool has_panel = false;
    474	bool has_ck505 = false;
    475	bool can_ssc = false;
    476	bool using_ssc_source = false;
    477
    478	/* We need to take the global config into account */
    479	for_each_intel_encoder(&dev_priv->drm, encoder) {
    480		switch (encoder->type) {
    481		case INTEL_OUTPUT_LVDS:
    482			has_panel = true;
    483			has_lvds = true;
    484			break;
    485		case INTEL_OUTPUT_EDP:
    486			has_panel = true;
    487			if (encoder->port == PORT_A)
    488				has_cpu_edp = true;
    489			break;
    490		default:
    491			break;
    492		}
    493	}
    494
    495	if (HAS_PCH_IBX(dev_priv)) {
    496		has_ck505 = dev_priv->vbt.display_clock_mode;
    497		can_ssc = has_ck505;
    498	} else {
    499		has_ck505 = false;
    500		can_ssc = true;
    501	}
    502
    503	/* Check if any DPLLs are using the SSC source */
    504	for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) {
    505		u32 temp = intel_de_read(dev_priv, PCH_DPLL(i));
    506
    507		if (!(temp & DPLL_VCO_ENABLE))
    508			continue;
    509
    510		if ((temp & PLL_REF_INPUT_MASK) ==
    511		    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
    512			using_ssc_source = true;
    513			break;
    514		}
    515	}
    516
    517	drm_dbg_kms(&dev_priv->drm,
    518		    "has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
    519		    has_panel, has_lvds, has_ck505, using_ssc_source);
    520
    521	/* Ironlake: try to setup display ref clock before DPLL
    522	 * enabling. This is only under driver's control after
    523	 * PCH B stepping, previous chipset stepping should be
    524	 * ignoring this setting.
    525	 */
    526	val = intel_de_read(dev_priv, PCH_DREF_CONTROL);
    527
    528	/* As we must carefully and slowly disable/enable each source in turn,
    529	 * compute the final state we want first and check if we need to
    530	 * make any changes at all.
    531	 */
    532	final = val;
    533	final &= ~DREF_NONSPREAD_SOURCE_MASK;
    534	if (has_ck505)
    535		final |= DREF_NONSPREAD_CK505_ENABLE;
    536	else
    537		final |= DREF_NONSPREAD_SOURCE_ENABLE;
    538
    539	final &= ~DREF_SSC_SOURCE_MASK;
    540	final &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
    541	final &= ~DREF_SSC1_ENABLE;
    542
    543	if (has_panel) {
    544		final |= DREF_SSC_SOURCE_ENABLE;
    545
    546		if (intel_panel_use_ssc(dev_priv) && can_ssc)
    547			final |= DREF_SSC1_ENABLE;
    548
    549		if (has_cpu_edp) {
    550			if (intel_panel_use_ssc(dev_priv) && can_ssc)
    551				final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
    552			else
    553				final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
    554		} else {
    555			final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
    556		}
    557	} else if (using_ssc_source) {
    558		final |= DREF_SSC_SOURCE_ENABLE;
    559		final |= DREF_SSC1_ENABLE;
    560	}
    561
    562	if (final == val)
    563		return;
    564
    565	/* Always enable nonspread source */
    566	val &= ~DREF_NONSPREAD_SOURCE_MASK;
    567
    568	if (has_ck505)
    569		val |= DREF_NONSPREAD_CK505_ENABLE;
    570	else
    571		val |= DREF_NONSPREAD_SOURCE_ENABLE;
    572
    573	if (has_panel) {
    574		val &= ~DREF_SSC_SOURCE_MASK;
    575		val |= DREF_SSC_SOURCE_ENABLE;
    576
    577		/* SSC must be turned on before enabling the CPU output  */
    578		if (intel_panel_use_ssc(dev_priv) && can_ssc) {
    579			drm_dbg_kms(&dev_priv->drm, "Using SSC on panel\n");
    580			val |= DREF_SSC1_ENABLE;
    581		} else {
    582			val &= ~DREF_SSC1_ENABLE;
    583		}
    584
    585		/* Get SSC going before enabling the outputs */
    586		intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
    587		intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
    588		udelay(200);
    589
    590		val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
    591
    592		/* Enable CPU source on CPU attached eDP */
    593		if (has_cpu_edp) {
    594			if (intel_panel_use_ssc(dev_priv) && can_ssc) {
    595				drm_dbg_kms(&dev_priv->drm,
    596					    "Using SSC on eDP\n");
    597				val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
    598			} else {
    599				val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
    600			}
    601		} else {
    602			val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
    603		}
    604
    605		intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
    606		intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
    607		udelay(200);
    608	} else {
    609		drm_dbg_kms(&dev_priv->drm, "Disabling CPU source output\n");
    610
    611		val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
    612
    613		/* Turn off CPU output */
    614		val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
    615
    616		intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
    617		intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
    618		udelay(200);
    619
    620		if (!using_ssc_source) {
    621			drm_dbg_kms(&dev_priv->drm, "Disabling SSC source\n");
    622
    623			/* Turn off the SSC source */
    624			val &= ~DREF_SSC_SOURCE_MASK;
    625			val |= DREF_SSC_SOURCE_DISABLE;
    626
    627			/* Turn off SSC1 */
    628			val &= ~DREF_SSC1_ENABLE;
    629
    630			intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
    631			intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
    632			udelay(200);
    633		}
    634	}
    635
    636	BUG_ON(val != final);
    637}
    638
    639/*
    640 * Initialize reference clocks when the driver loads
    641 */
    642void intel_init_pch_refclk(struct drm_i915_private *dev_priv)
    643{
    644	if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
    645		ilk_init_pch_refclk(dev_priv);
    646	else if (HAS_PCH_LPT(dev_priv))
    647		lpt_init_pch_refclk(dev_priv);
    648}