diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dpll.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_dpll.c | 519 | 
1 files changed, 514 insertions, 5 deletions
| diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 7ba7f315aaee..3e3c5eed1600 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -3,11 +3,13 @@   * Copyright © 2020 Intel Corporation   */  #include <linux/kernel.h> +#include "intel_crtc.h"  #include "intel_display_types.h"  #include "intel_display.h"  #include "intel_dpll.h"  #include "intel_lvds.h"  #include "intel_panel.h" +#include "intel_sideband.h"  struct intel_limit {  	struct { @@ -845,7 +847,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,  		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;  		break;  	} -	if (INTEL_GEN(dev_priv) >= 4) +	if (DISPLAY_VER(dev_priv) >= 4)  		dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);  	if (crtc_state->sdvo_tv_clock) @@ -859,7 +861,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,  	dpll |= DPLL_VCO_ENABLE;  	crtc_state->dpll_hw_state.dpll = dpll; -	if (INTEL_GEN(dev_priv) >= 4) { +	if (DISPLAY_VER(dev_priv) >= 4) {  		u32 dpll_md = (crtc_state->pixel_multiplier - 1)  			<< DPLL_MD_UDI_MULTIPLIER_SHIFT;  		crtc_state->dpll_hw_state.dpll_md = dpll_md; @@ -924,7 +926,7 @@ static int hsw_crtc_compute_clock(struct intel_crtc *crtc,  		to_intel_atomic_state(crtc_state->uapi.state);  	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) || -	    INTEL_GEN(dev_priv) >= 11) { +	    DISPLAY_VER(dev_priv) >= 11) {  		struct intel_encoder *encoder =  			intel_get_crtc_new_encoder(state, crtc_state); @@ -1344,7 +1346,7 @@ static int i8xx_crtc_compute_clock(struct intel_crtc *crtc,  void  intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv)  { -	if (INTEL_GEN(dev_priv) >= 9 || HAS_DDI(dev_priv)) +	if (DISPLAY_VER(dev_priv) >= 9 || HAS_DDI(dev_priv))  		dev_priv->display.crtc_compute_clock = hsw_crtc_compute_clock;  	else if (HAS_PCH_SPLIT(dev_priv))  		dev_priv->display.crtc_compute_clock = ilk_crtc_compute_clock; @@ -1356,8 +1358,515 @@ intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv)  		dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock;  	else if (IS_PINEVIEW(dev_priv))  		dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock; -	else if (!IS_GEN(dev_priv, 2)) +	else if (!IS_DISPLAY_VER(dev_priv, 2))  		dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;  	else  		dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock;  } + +static bool i9xx_has_pps(struct drm_i915_private *dev_priv) +{ +	if (IS_I830(dev_priv)) +		return false; + +	return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); +} + +void i9xx_enable_pll(struct intel_crtc *crtc, +		     const struct intel_crtc_state *crtc_state) +{ +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	i915_reg_t reg = DPLL(crtc->pipe); +	u32 dpll = crtc_state->dpll_hw_state.dpll; +	int i; + +	assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder); + +	/* PLL is protected by panel, make sure we can write it */ +	if (i9xx_has_pps(dev_priv)) +		assert_panel_unlocked(dev_priv, crtc->pipe); + +	/* +	 * Apparently we need to have VGA mode enabled prior to changing +	 * the P1/P2 dividers. Otherwise the DPLL will keep using the old +	 * dividers, even though the register value does change. +	 */ +	intel_de_write(dev_priv, reg, dpll & ~DPLL_VGA_MODE_DIS); +	intel_de_write(dev_priv, reg, dpll); + +	/* Wait for the clocks to stabilize. */ +	intel_de_posting_read(dev_priv, reg); +	udelay(150); + +	if (DISPLAY_VER(dev_priv) >= 4) { +		intel_de_write(dev_priv, DPLL_MD(crtc->pipe), +			       crtc_state->dpll_hw_state.dpll_md); +	} else { +		/* The pixel multiplier can only be updated once the +		 * DPLL is enabled and the clocks are stable. +		 * +		 * So write it again. +		 */ +		intel_de_write(dev_priv, reg, dpll); +	} + +	/* We do this three times for luck */ +	for (i = 0; i < 3; i++) { +		intel_de_write(dev_priv, reg, dpll); +		intel_de_posting_read(dev_priv, reg); +		udelay(150); /* wait for warmup */ +	} +} + +static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, +				 enum pipe pipe) +{ +	u32 reg_val; + +	/* +	 * PLLB opamp always calibrates to max value of 0x3f, force enable it +	 * and set it to a reasonable value instead. +	 */ +	reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); +	reg_val &= 0xffffff00; +	reg_val |= 0x00000030; +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); + +	reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); +	reg_val &= 0x00ffffff; +	reg_val |= 0x8c000000; +	vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); + +	reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); +	reg_val &= 0xffffff00; +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); + +	reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); +	reg_val &= 0x00ffffff; +	reg_val |= 0xb0000000; +	vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); +} + +static void _vlv_enable_pll(struct intel_crtc *crtc, +			    const struct intel_crtc_state *pipe_config) +{ +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; + +	intel_de_write(dev_priv, DPLL(pipe), pipe_config->dpll_hw_state.dpll); +	intel_de_posting_read(dev_priv, DPLL(pipe)); +	udelay(150); + +	if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1)) +		drm_err(&dev_priv->drm, "DPLL %d failed to lock\n", pipe); +} + +void vlv_enable_pll(struct intel_crtc *crtc, +		    const struct intel_crtc_state *pipe_config) +{ +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; + +	assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder); + +	/* PLL is protected by panel, make sure we can write it */ +	assert_panel_unlocked(dev_priv, pipe); + +	if (pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) +		_vlv_enable_pll(crtc, pipe_config); + +	intel_de_write(dev_priv, DPLL_MD(pipe), +		       pipe_config->dpll_hw_state.dpll_md); +	intel_de_posting_read(dev_priv, DPLL_MD(pipe)); +} + + +static void _chv_enable_pll(struct intel_crtc *crtc, +			    const struct intel_crtc_state *pipe_config) +{ +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; +	enum dpio_channel port = vlv_pipe_to_channel(pipe); +	u32 tmp; + +	vlv_dpio_get(dev_priv); + +	/* Enable back the 10bit clock to display controller */ +	tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)); +	tmp |= DPIO_DCLKP_EN; +	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), tmp); + +	vlv_dpio_put(dev_priv); + +	/* +	 * Need to wait > 100ns between dclkp clock enable bit and PLL enable. +	 */ +	udelay(1); + +	/* Enable PLL */ +	intel_de_write(dev_priv, DPLL(pipe), pipe_config->dpll_hw_state.dpll); + +	/* Check PLL is locked */ +	if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1)) +		drm_err(&dev_priv->drm, "PLL %d failed to lock\n", pipe); +} + +void chv_enable_pll(struct intel_crtc *crtc, +		    const struct intel_crtc_state *pipe_config) +{ +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; + +	assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder); + +	/* PLL is protected by panel, make sure we can write it */ +	assert_panel_unlocked(dev_priv, pipe); + +	if (pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) +		_chv_enable_pll(crtc, pipe_config); + +	if (pipe != PIPE_A) { +		/* +		 * WaPixelRepeatModeFixForC0:chv +		 * +		 * DPLLCMD is AWOL. Use chicken bits to propagate +		 * the value from DPLLBMD to either pipe B or C. +		 */ +		intel_de_write(dev_priv, CBR4_VLV, CBR_DPLLBMD_PIPE(pipe)); +		intel_de_write(dev_priv, DPLL_MD(PIPE_B), +			       pipe_config->dpll_hw_state.dpll_md); +		intel_de_write(dev_priv, CBR4_VLV, 0); +		dev_priv->chv_dpll_md[pipe] = pipe_config->dpll_hw_state.dpll_md; + +		/* +		 * DPLLB VGA mode also seems to cause problems. +		 * We should always have it disabled. +		 */ +		drm_WARN_ON(&dev_priv->drm, +			    (intel_de_read(dev_priv, DPLL(PIPE_B)) & +			     DPLL_VGA_MODE_DIS) == 0); +	} else { +		intel_de_write(dev_priv, DPLL_MD(pipe), +			       pipe_config->dpll_hw_state.dpll_md); +		intel_de_posting_read(dev_priv, DPLL_MD(pipe)); +	} +} + +void vlv_prepare_pll(struct intel_crtc *crtc, +		     const struct intel_crtc_state *pipe_config) +{ +	struct drm_device *dev = crtc->base.dev; +	struct drm_i915_private *dev_priv = to_i915(dev); +	enum pipe pipe = crtc->pipe; +	u32 mdiv; +	u32 bestn, bestm1, bestm2, bestp1, bestp2; +	u32 coreclk, reg_val; + +	/* Enable Refclk */ +	intel_de_write(dev_priv, DPLL(pipe), +		       pipe_config->dpll_hw_state.dpll & ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV)); + +	/* No need to actually set up the DPLL with DSI */ +	if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0) +		return; + +	vlv_dpio_get(dev_priv); + +	bestn = pipe_config->dpll.n; +	bestm1 = pipe_config->dpll.m1; +	bestm2 = pipe_config->dpll.m2; +	bestp1 = pipe_config->dpll.p1; +	bestp2 = pipe_config->dpll.p2; + +	/* See eDP HDMI DPIO driver vbios notes doc */ + +	/* PLL B needs special handling */ +	if (pipe == PIPE_B) +		vlv_pllb_recal_opamp(dev_priv, pipe); + +	/* Set up Tx target for periodic Rcomp update */ +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f); + +	/* Disable target IRef on PLL */ +	reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe)); +	reg_val &= 0x00ffffff; +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val); + +	/* Disable fast lock */ +	vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610); + +	/* Set idtafcrecal before PLL is enabled */ +	mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); +	mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); +	mdiv |= ((bestn << DPIO_N_SHIFT)); +	mdiv |= (1 << DPIO_K_SHIFT); + +	/* +	 * Post divider depends on pixel clock rate, DAC vs digital (and LVDS, +	 * but we don't support that). +	 * Note: don't use the DAC post divider as it seems unstable. +	 */ +	mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); + +	mdiv |= DPIO_ENABLE_CALIBRATION; +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); + +	/* Set HBR and RBR LPF coefficients */ +	if (pipe_config->port_clock == 162000 || +	    intel_crtc_has_type(pipe_config, INTEL_OUTPUT_ANALOG) || +	    intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) +		vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), +				 0x009f0003); +	else +		vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), +				 0x00d0000f); + +	if (intel_crtc_has_dp_encoder(pipe_config)) { +		/* Use SSC source */ +		if (pipe == PIPE_A) +			vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), +					 0x0df40000); +		else +			vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), +					 0x0df70000); +	} else { /* HDMI or VGA */ +		/* Use bend source */ +		if (pipe == PIPE_A) +			vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), +					 0x0df70000); +		else +			vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), +					 0x0df40000); +	} + +	coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe)); +	coreclk = (coreclk & 0x0000ff00) | 0x01c00000; +	if (intel_crtc_has_dp_encoder(pipe_config)) +		coreclk |= 0x01000000; +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk); + +	vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000); + +	vlv_dpio_put(dev_priv); +} + +void chv_prepare_pll(struct intel_crtc *crtc, +		     const struct intel_crtc_state *pipe_config) +{ +	struct drm_device *dev = crtc->base.dev; +	struct drm_i915_private *dev_priv = to_i915(dev); +	enum pipe pipe = crtc->pipe; +	enum dpio_channel port = vlv_pipe_to_channel(pipe); +	u32 loopfilter, tribuf_calcntr; +	u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac; +	u32 dpio_val; +	int vco; + +	/* Enable Refclk and SSC */ +	intel_de_write(dev_priv, DPLL(pipe), +		       pipe_config->dpll_hw_state.dpll & ~DPLL_VCO_ENABLE); + +	/* No need to actually set up the DPLL with DSI */ +	if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0) +		return; + +	bestn = pipe_config->dpll.n; +	bestm2_frac = pipe_config->dpll.m2 & 0x3fffff; +	bestm1 = pipe_config->dpll.m1; +	bestm2 = pipe_config->dpll.m2 >> 22; +	bestp1 = pipe_config->dpll.p1; +	bestp2 = pipe_config->dpll.p2; +	vco = pipe_config->dpll.vco; +	dpio_val = 0; +	loopfilter = 0; + +	vlv_dpio_get(dev_priv); + +	/* p1 and p2 divider */ +	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port), +			5 << DPIO_CHV_S1_DIV_SHIFT | +			bestp1 << DPIO_CHV_P1_DIV_SHIFT | +			bestp2 << DPIO_CHV_P2_DIV_SHIFT | +			1 << DPIO_CHV_K_DIV_SHIFT); + +	/* Feedback post-divider - m2 */ +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW0(port), bestm2); + +	/* Feedback refclk divider - n and m1 */ +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW1(port), +			DPIO_CHV_M1_DIV_BY_2 | +			1 << DPIO_CHV_N_DIV_SHIFT); + +	/* M2 fraction division */ +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac); + +	/* M2 fraction division enable */ +	dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port)); +	dpio_val &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN); +	dpio_val |= (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT); +	if (bestm2_frac) +		dpio_val |= DPIO_CHV_FRAC_DIV_EN; +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port), dpio_val); + +	/* Program digital lock detect threshold */ +	dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW9(port)); +	dpio_val &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK | +					DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE); +	dpio_val |= (0x5 << DPIO_CHV_INT_LOCK_THRESHOLD_SHIFT); +	if (!bestm2_frac) +		dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE; +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW9(port), dpio_val); + +	/* Loop filter */ +	if (vco == 5400000) { +		loopfilter |= (0x3 << DPIO_CHV_PROP_COEFF_SHIFT); +		loopfilter |= (0x8 << DPIO_CHV_INT_COEFF_SHIFT); +		loopfilter |= (0x1 << DPIO_CHV_GAIN_CTRL_SHIFT); +		tribuf_calcntr = 0x9; +	} else if (vco <= 6200000) { +		loopfilter |= (0x5 << DPIO_CHV_PROP_COEFF_SHIFT); +		loopfilter |= (0xB << DPIO_CHV_INT_COEFF_SHIFT); +		loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT); +		tribuf_calcntr = 0x9; +	} else if (vco <= 6480000) { +		loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT); +		loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT); +		loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT); +		tribuf_calcntr = 0x8; +	} else { +		/* Not supported. Apply the same limits as in the max case */ +		loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT); +		loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT); +		loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT); +		tribuf_calcntr = 0; +	} +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter); + +	dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW8(port)); +	dpio_val &= ~DPIO_CHV_TDC_TARGET_CNT_MASK; +	dpio_val |= (tribuf_calcntr << DPIO_CHV_TDC_TARGET_CNT_SHIFT); +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW8(port), dpio_val); + +	/* AFC Recal */ +	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), +			vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) | +			DPIO_AFC_RECAL); + +	vlv_dpio_put(dev_priv); +} + +/** + * vlv_force_pll_on - forcibly enable just the PLL + * @dev_priv: i915 private structure + * @pipe: pipe PLL to enable + * @dpll: PLL configuration + * + * Enable the PLL for @pipe using the supplied @dpll config. To be used + * in cases where we need the PLL enabled even when @pipe is not going to + * be enabled. + */ +int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, +		     const struct dpll *dpll) +{ +	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); +	struct intel_crtc_state *pipe_config; + +	pipe_config = intel_crtc_state_alloc(crtc); +	if (!pipe_config) +		return -ENOMEM; + +	pipe_config->cpu_transcoder = (enum transcoder)pipe; +	pipe_config->pixel_multiplier = 1; +	pipe_config->dpll = *dpll; + +	if (IS_CHERRYVIEW(dev_priv)) { +		chv_compute_dpll(crtc, pipe_config); +		chv_prepare_pll(crtc, pipe_config); +		chv_enable_pll(crtc, pipe_config); +	} else { +		vlv_compute_dpll(crtc, pipe_config); +		vlv_prepare_pll(crtc, pipe_config); +		vlv_enable_pll(crtc, pipe_config); +	} + +	kfree(pipe_config); + +	return 0; +} + +void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) +{ +	u32 val; + +	/* Make sure the pipe isn't still relying on us */ +	assert_pipe_disabled(dev_priv, (enum transcoder)pipe); + +	val = DPLL_INTEGRATED_REF_CLK_VLV | +		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; +	if (pipe != PIPE_A) +		val |= DPLL_INTEGRATED_CRI_CLK_VLV; + +	intel_de_write(dev_priv, DPLL(pipe), val); +	intel_de_posting_read(dev_priv, DPLL(pipe)); +} + +void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) +{ +	enum dpio_channel port = vlv_pipe_to_channel(pipe); +	u32 val; + +	/* Make sure the pipe isn't still relying on us */ +	assert_pipe_disabled(dev_priv, (enum transcoder)pipe); + +	val = DPLL_SSC_REF_CLK_CHV | +		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; +	if (pipe != PIPE_A) +		val |= DPLL_INTEGRATED_CRI_CLK_VLV; + +	intel_de_write(dev_priv, DPLL(pipe), val); +	intel_de_posting_read(dev_priv, DPLL(pipe)); + +	vlv_dpio_get(dev_priv); + +	/* Disable 10bit clock to display controller */ +	val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)); +	val &= ~DPIO_DCLKP_EN; +	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val); + +	vlv_dpio_put(dev_priv); +} + +void i9xx_disable_pll(const struct intel_crtc_state *crtc_state) +{ +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; + +	/* Don't disable pipe or pipe PLLs if needed */ +	if (IS_I830(dev_priv)) +		return; + +	/* Make sure the pipe isn't still relying on us */ +	assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder); + +	intel_de_write(dev_priv, DPLL(pipe), DPLL_VGA_MODE_DIS); +	intel_de_posting_read(dev_priv, DPLL(pipe)); +} + + +/** + * vlv_force_pll_off - forcibly disable just the PLL + * @dev_priv: i915 private structure + * @pipe: pipe PLL to disable + * + * Disable the PLL for @pipe. To be used in cases where we need + * the PLL enabled even when @pipe is not going to be enabled. + */ +void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe) +{ +	if (IS_CHERRYVIEW(dev_priv)) +		chv_disable_pll(dev_priv, pipe); +	else +		vlv_disable_pll(dev_priv, pipe); +} | 
