diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 912 | 
1 files changed, 732 insertions, 180 deletions
| diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 3eb0efc2dd0d..cacb07b7a8f1 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -155,33 +155,100 @@ static const struct ddi_buf_trans skl_ddi_translations_edp[] = {  static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { -					/* Idx	NT mV   T mV    db  */ -	{ 0x00004014, 0x00000087 },	/* 0:	800	1000	2   */ +	{ 0x00000018, 0x000000ac }, +	{ 0x00005012, 0x0000009d }, +	{ 0x00007011, 0x00000088 }, +	{ 0x00000018, 0x000000a1 }, +	{ 0x00000018, 0x00000098 }, +	{ 0x00004013, 0x00000088 }, +	{ 0x00006012, 0x00000087 }, +	{ 0x00000018, 0x000000df }, +	{ 0x00003015, 0x00000087 }, +	{ 0x00003015, 0x000000c7 }, +	{ 0x00000018, 0x000000c7 },  }; -enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) +struct bxt_ddi_buf_trans { +	u32 margin;	/* swing value */ +	u32 scale;	/* scale value */ +	u32 enable;	/* scale enable */ +	u32 deemphasis; +	bool default_index; /* true if the entry represents default value */ +}; + +/* BSpec does not define separate vswing/pre-emphasis values for eDP. + * Using DP values for eDP as well. + */ +static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { +					/* Idx	NT mV diff	db  */ +	{ 52,  0,    0, 128, true  },	/* 0:	400		0   */ +	{ 78,  0,    0, 85,  false },	/* 1:	400		3.5 */ +	{ 104, 0,    0, 64,  false },	/* 2:	400		6   */ +	{ 154, 0,    0, 43,  false },	/* 3:	400		9.5 */ +	{ 77,  0,    0, 128, false },	/* 4:	600		0   */ +	{ 116, 0,    0, 85,  false },	/* 5:	600		3.5 */ +	{ 154, 0,    0, 64,  false },	/* 6:	600		6   */ +	{ 102, 0,    0, 128, false },	/* 7:	800		0   */ +	{ 154, 0,    0, 85,  false },	/* 8:	800		3.5 */ +	{ 154, 0x9A, 1, 128, false },  /* 9:	1200		0   */ +}; + +/* BSpec has 2 recommended values - entries 0 and 8. + * Using the entry with higher vswing. + */ +static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { +					/* Idx	NT mV diff	db  */ +	{ 52,  0,    0, 128, false },	/* 0:	400		0   */ +	{ 52,  0,    0, 85,  false },	/* 1:	400		3.5 */ +	{ 52,  0,    0, 64,  false },	/* 2:	400		6   */ +	{ 42,  0,    0, 43,  false },	/* 3:	400		9.5 */ +	{ 77,  0,    0, 128, false },	/* 4:	600		0   */ +	{ 77,  0,    0, 85,  false },	/* 5:	600		3.5 */ +	{ 77,  0,    0, 64,  false },	/* 6:	600		6   */ +	{ 102, 0,    0, 128, false },	/* 7:	800		0   */ +	{ 102, 0,    0, 85,  false },	/* 8:	800		3.5 */ +	{ 154, 0x9A, 1, 128, true },	/* 9:	1200		0   */ +}; + +static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, +				 struct intel_digital_port **dig_port, +				 enum port *port)  {  	struct drm_encoder *encoder = &intel_encoder->base;  	int type = intel_encoder->type;  	if (type == INTEL_OUTPUT_DP_MST) { -		struct intel_digital_port *intel_dig_port = enc_to_mst(encoder)->primary; -		return intel_dig_port->port; +		*dig_port = enc_to_mst(encoder)->primary; +		*port = (*dig_port)->port;  	} else if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||  	    type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) { -		struct intel_digital_port *intel_dig_port = -			enc_to_dig_port(encoder); -		return intel_dig_port->port; - +		*dig_port = enc_to_dig_port(encoder); +		*port = (*dig_port)->port;  	} else if (type == INTEL_OUTPUT_ANALOG) { -		return PORT_E; - +		*dig_port = NULL; +		*port = PORT_E;  	} else {  		DRM_ERROR("Invalid DDI encoder type %d\n", type);  		BUG();  	}  } +enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) +{ +	struct intel_digital_port *dig_port; +	enum port port; + +	ddi_get_encoder_port(intel_encoder, &dig_port, &port); + +	return port; +} + +static bool +intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) +{ +	return intel_dig_port->hdmi.hdmi_reg; +} +  /*   * Starting with Haswell, DDI port buffers must be programmed with correct   * values in advance. The buffer values are different for FDI and DP modes, @@ -189,7 +256,8 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)   * in either FDI or DP modes only, as HDMI connections will work with both   * of those   */ -static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) +static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, +				      bool supports_hdmi)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 reg; @@ -202,11 +270,19 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)  	const struct ddi_buf_trans *ddi_translations_hdmi;  	const struct ddi_buf_trans *ddi_translations; -	if (IS_SKYLAKE(dev)) { +	if (IS_BROXTON(dev)) { +		if (!supports_hdmi) +			return; + +		/* Vswing programming for HDMI */ +		bxt_ddi_vswing_sequence(dev, hdmi_level, port, +					INTEL_OUTPUT_HDMI); +		return; +	} else if (IS_SKYLAKE(dev)) {  		ddi_translations_fdi = NULL;  		ddi_translations_dp = skl_ddi_translations_dp;  		n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp); -		if (dev_priv->vbt.edp_low_vswing) { +		if (dev_priv->edp_low_vswing) {  			ddi_translations_edp = skl_ddi_translations_edp;  			n_edp_entries = ARRAY_SIZE(skl_ddi_translations_edp);  		} else { @@ -214,16 +290,9 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)  			n_edp_entries = ARRAY_SIZE(skl_ddi_translations_dp);  		} -		/* -		 * On SKL, the recommendation from the hw team is to always use -		 * a certain type of level shifter (and thus the corresponding -		 * 800mV+2dB entry). Given that's the only validated entry, we -		 * override what is in the VBT, at least until further notice. -		 */ -		hdmi_level = 0;  		ddi_translations_hdmi = skl_ddi_translations_hdmi;  		n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); -		hdmi_default_entry = 0; +		hdmi_default_entry = 7;  	} else if (IS_BROADWELL(dev)) {  		ddi_translations_fdi = bdw_ddi_translations_fdi;  		ddi_translations_dp = bdw_ddi_translations_dp; @@ -290,6 +359,9 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)  		reg += 4;  	} +	if (!supports_hdmi) +		return; +  	/* Choose a good default if VBT is badly populated */  	if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN ||  	    hdmi_level >= n_hdmi_entries) @@ -307,13 +379,28 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)   */  void intel_prepare_ddi(struct drm_device *dev)  { -	int port; +	struct intel_encoder *intel_encoder; +	bool visited[I915_MAX_PORTS] = { 0, };  	if (!HAS_DDI(dev))  		return; -	for (port = PORT_A; port <= PORT_E; port++) -		intel_prepare_ddi_buffers(dev, port); +	for_each_intel_encoder(dev, intel_encoder) { +		struct intel_digital_port *intel_dig_port; +		enum port port; +		bool supports_hdmi; + +		ddi_get_encoder_port(intel_encoder, &intel_dig_port, &port); + +		if (visited[port]) +			continue; + +		supports_hdmi = intel_dig_port && +				intel_dig_port_supports_hdmi(intel_dig_port); + +		intel_prepare_ddi_buffers(dev, port, supports_hdmi); +		visited[port] = true; +	}  }  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, @@ -322,7 +409,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,  	uint32_t reg = DDI_BUF_CTL(port);  	int i; -	for (i = 0; i < 8; i++) { +	for (i = 0; i < 16; i++) {  		udelay(1);  		if (I915_READ(reg) & DDI_BUF_IS_IDLE)  			return; @@ -491,23 +578,24 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)  	return ret;  } -static struct intel_encoder * +struct intel_encoder *  intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state)  {  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);  	struct intel_encoder *ret = NULL;  	struct drm_atomic_state *state; +	struct drm_connector *connector; +	struct drm_connector_state *connector_state;  	int num_encoders = 0;  	int i;  	state = crtc_state->base.state; -	for (i = 0; i < state->num_connector; i++) { -		if (!state->connectors[i] || -		    state->connector_states[i]->crtc != crtc_state->base.crtc) +	for_each_connector_in_state(state, connector, connector_state, i) { +		if (connector_state->crtc != crtc_state->base.crtc)  			continue; -		ret = to_intel_encoder(state->connector_states[i]->best_encoder); +		ret = to_intel_encoder(connector_state->best_encoder);  		num_encoders++;  	} @@ -783,26 +871,26 @@ static void skl_ddi_clock_get(struct intel_encoder *encoder,  	if (dpll_ctl1 & DPLL_CTRL1_HDMI_MODE(dpll)) {  		link_clock = skl_calc_wrpll_link(dev_priv, dpll);  	} else { -		link_clock = dpll_ctl1 & DPLL_CRTL1_LINK_RATE_MASK(dpll); -		link_clock >>= DPLL_CRTL1_LINK_RATE_SHIFT(dpll); +		link_clock = dpll_ctl1 & DPLL_CTRL1_LINK_RATE_MASK(dpll); +		link_clock >>= DPLL_CTRL1_LINK_RATE_SHIFT(dpll);  		switch (link_clock) { -		case DPLL_CRTL1_LINK_RATE_810: +		case DPLL_CTRL1_LINK_RATE_810:  			link_clock = 81000;  			break; -		case DPLL_CRTL1_LINK_RATE_1080: +		case DPLL_CTRL1_LINK_RATE_1080:  			link_clock = 108000;  			break; -		case DPLL_CRTL1_LINK_RATE_1350: +		case DPLL_CTRL1_LINK_RATE_1350:  			link_clock = 135000;  			break; -		case DPLL_CRTL1_LINK_RATE_1620: +		case DPLL_CTRL1_LINK_RATE_1620:  			link_clock = 162000;  			break; -		case DPLL_CRTL1_LINK_RATE_2160: +		case DPLL_CTRL1_LINK_RATE_2160:  			link_clock = 216000;  			break; -		case DPLL_CRTL1_LINK_RATE_2700: +		case DPLL_CTRL1_LINK_RATE_2700:  			link_clock = 270000;  			break;  		default: @@ -878,6 +966,32 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder,  		pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;  } +static int bxt_calc_pll_link(struct drm_i915_private *dev_priv, +				enum intel_dpll_id dpll) +{ +	/* FIXME formula not available in bspec */ +	return 0; +} + +static void bxt_ddi_clock_get(struct intel_encoder *encoder, +				struct intel_crtc_state *pipe_config) +{ +	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; +	enum port port = intel_ddi_get_encoder_port(encoder); +	uint32_t dpll = port; + +	pipe_config->port_clock = +		bxt_calc_pll_link(dev_priv, dpll); + +	if (pipe_config->has_dp_encoder) +		pipe_config->base.adjusted_mode.crtc_clock = +			intel_dotclock_calculate(pipe_config->port_clock, +							&pipe_config->dp_m_n); +	else +		pipe_config->base.adjusted_mode.crtc_clock = +							pipe_config->port_clock; +} +  void intel_ddi_clock_get(struct intel_encoder *encoder,  			 struct intel_crtc_state *pipe_config)  { @@ -885,8 +999,10 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,  	if (INTEL_INFO(dev)->gen <= 8)  		hsw_ddi_clock_get(encoder, pipe_config); -	else +	else if (IS_SKYLAKE(dev))  		skl_ddi_clock_get(encoder, pipe_config); +	else if (IS_BROXTON(dev)) +		bxt_ddi_clock_get(encoder, pipe_config);  }  static void @@ -971,6 +1087,9 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,  		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |  		      WRPLL_DIVIDER_POST(p); +		memset(&crtc_state->dpll_hw_state, 0, +		       sizeof(crtc_state->dpll_hw_state)); +  		crtc_state->dpll_hw_state.wrpll = val;  		pll = intel_get_shared_dpll(intel_crtc, crtc_state); @@ -1073,69 +1192,69 @@ found:  	if (min_dco_index > 2) {  		WARN(1, "No valid values found for the given pixel clock\n");  	} else { -		 wrpll_params->central_freq = dco_central_freq[min_dco_index]; +		wrpll_params->central_freq = dco_central_freq[min_dco_index]; -		 switch (dco_central_freq[min_dco_index]) { -		 case 9600000000ULL: +		switch (dco_central_freq[min_dco_index]) { +		case 9600000000ULL:  			wrpll_params->central_freq = 0;  			break; -		 case 9000000000ULL: +		case 9000000000ULL:  			wrpll_params->central_freq = 1;  			break; -		 case 8400000000ULL: +		case 8400000000ULL:  			wrpll_params->central_freq = 3; -		 } +		} -		 switch (candidate_p0[min_dco_index]) { -		 case 1: +		switch (candidate_p0[min_dco_index]) { +		case 1:  			wrpll_params->pdiv = 0;  			break; -		 case 2: +		case 2:  			wrpll_params->pdiv = 1;  			break; -		 case 3: +		case 3:  			wrpll_params->pdiv = 2;  			break; -		 case 7: +		case 7:  			wrpll_params->pdiv = 4;  			break; -		 default: +		default:  			WARN(1, "Incorrect PDiv\n"); -		 } +		} -		 switch (candidate_p2[min_dco_index]) { -		 case 5: +		switch (candidate_p2[min_dco_index]) { +		case 5:  			wrpll_params->kdiv = 0;  			break; -		 case 2: +		case 2:  			wrpll_params->kdiv = 1;  			break; -		 case 3: +		case 3:  			wrpll_params->kdiv = 2;  			break; -		 case 1: +		case 1:  			wrpll_params->kdiv = 3;  			break; -		 default: +		default:  			WARN(1, "Incorrect KDiv\n"); -		 } +		} -		 wrpll_params->qdiv_ratio = candidate_p1[min_dco_index]; -		 wrpll_params->qdiv_mode = +		wrpll_params->qdiv_ratio = candidate_p1[min_dco_index]; +		wrpll_params->qdiv_mode =  			(wrpll_params->qdiv_ratio == 1) ? 0 : 1; -		 dco_freq = candidate_p0[min_dco_index] * -			 candidate_p1[min_dco_index] * -			 candidate_p2[min_dco_index] * afe_clock; +		dco_freq = candidate_p0[min_dco_index] * +			candidate_p1[min_dco_index] * +			candidate_p2[min_dco_index] * afe_clock;  		/* -		* Intermediate values are in Hz. -		* Divide by MHz to match bsepc -		*/ -		 wrpll_params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); -		 wrpll_params->dco_fraction = -			 div_u64(((div_u64(dco_freq, 24) - -				   wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1)); +		 * Intermediate values are in Hz. +		 * Divide by MHz to match bsepc +		 */ +		wrpll_params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); +		wrpll_params->dco_fraction = +			div_u64(((div_u64(dco_freq, 24) - +				  wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1));  	}  } @@ -1179,13 +1298,13 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,  		switch (intel_dp->link_bw) {  		case DP_LINK_BW_1_62: -			ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_810, 0); +			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);  			break;  		case DP_LINK_BW_2_7: -			ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1350, 0); +			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);  			break;  		case DP_LINK_BW_5_4: -			ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_2700, 0); +			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);  			break;  		} @@ -1193,6 +1312,9 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,  	} else /* eDP */  		return true; +	memset(&crtc_state->dpll_hw_state, 0, +	       sizeof(crtc_state->dpll_hw_state)); +  	crtc_state->dpll_hw_state.ctrl1 = ctrl1;  	crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;  	crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; @@ -1210,6 +1332,161 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,  	return true;  } +/* bxt clock parameters */ +struct bxt_clk_div { +	uint32_t p1; +	uint32_t p2; +	uint32_t m2_int; +	uint32_t m2_frac; +	bool m2_frac_en; +	uint32_t n; +}; + +/* pre-calculated values for DP linkrates */ +static struct bxt_clk_div bxt_dp_clk_val[7] = { +	/* 162 */ {4, 2, 32, 1677722, 1, 1}, +	/* 270 */ {4, 1, 27,       0, 0, 1}, +	/* 540 */ {2, 1, 27,       0, 0, 1}, +	/* 216 */ {3, 2, 32, 1677722, 1, 1}, +	/* 243 */ {4, 1, 24, 1258291, 1, 1}, +	/* 324 */ {4, 1, 32, 1677722, 1, 1}, +	/* 432 */ {3, 1, 32, 1677722, 1, 1} +}; + +static bool +bxt_ddi_pll_select(struct intel_crtc *intel_crtc, +		   struct intel_crtc_state *crtc_state, +		   struct intel_encoder *intel_encoder, +		   int clock) +{ +	struct intel_shared_dpll *pll; +	struct bxt_clk_div clk_div = {0}; +	int vco = 0; +	uint32_t prop_coef, int_coef, gain_ctl, targ_cnt; +	uint32_t dcoampovr_en_h, dco_amp, lanestagger; + +	if (intel_encoder->type == INTEL_OUTPUT_HDMI) { +		intel_clock_t best_clock; + +		/* Calculate HDMI div */ +		/* +		 * FIXME: tie the following calculation into +		 * i9xx_crtc_compute_clock +		 */ +		if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) { +			DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n", +					 clock, pipe_name(intel_crtc->pipe)); +			return false; +		} + +		clk_div.p1 = best_clock.p1; +		clk_div.p2 = best_clock.p2; +		WARN_ON(best_clock.m1 != 2); +		clk_div.n = best_clock.n; +		clk_div.m2_int = best_clock.m2 >> 22; +		clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1); +		clk_div.m2_frac_en = clk_div.m2_frac != 0; + +		vco = best_clock.vco; +	} else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT || +			intel_encoder->type == INTEL_OUTPUT_EDP) { +		struct drm_encoder *encoder = &intel_encoder->base; +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + +		switch (intel_dp->link_bw) { +		case DP_LINK_BW_1_62: +			clk_div = bxt_dp_clk_val[0]; +			break; +		case DP_LINK_BW_2_7: +			clk_div = bxt_dp_clk_val[1]; +			break; +		case DP_LINK_BW_5_4: +			clk_div = bxt_dp_clk_val[2]; +			break; +		default: +			clk_div = bxt_dp_clk_val[0]; +			DRM_ERROR("Unknown link rate\n"); +		} +		vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2; +	} + +	dco_amp = 15; +	dcoampovr_en_h = 0; +	if (vco >= 6200000 && vco <= 6480000) { +		prop_coef = 4; +		int_coef = 9; +		gain_ctl = 3; +		targ_cnt = 8; +	} else if ((vco > 5400000 && vco < 6200000) || +			(vco >= 4800000 && vco < 5400000)) { +		prop_coef = 5; +		int_coef = 11; +		gain_ctl = 3; +		targ_cnt = 9; +		if (vco >= 4800000 && vco < 5400000) +			dcoampovr_en_h = 1; +	} else if (vco == 5400000) { +		prop_coef = 3; +		int_coef = 8; +		gain_ctl = 1; +		targ_cnt = 9; +	} else { +		DRM_ERROR("Invalid VCO\n"); +		return false; +	} + +	memset(&crtc_state->dpll_hw_state, 0, +	       sizeof(crtc_state->dpll_hw_state)); + +	if (clock > 270000) +		lanestagger = 0x18; +	else if (clock > 135000) +		lanestagger = 0x0d; +	else if (clock > 67000) +		lanestagger = 0x07; +	else if (clock > 33000) +		lanestagger = 0x04; +	else +		lanestagger = 0x02; + +	crtc_state->dpll_hw_state.ebb0 = +		PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2); +	crtc_state->dpll_hw_state.pll0 = clk_div.m2_int; +	crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n); +	crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac; + +	if (clk_div.m2_frac_en) +		crtc_state->dpll_hw_state.pll3 = +			PORT_PLL_M2_FRAC_ENABLE; + +	crtc_state->dpll_hw_state.pll6 = +		prop_coef | PORT_PLL_INT_COEFF(int_coef); +	crtc_state->dpll_hw_state.pll6 |= +		PORT_PLL_GAIN_CTL(gain_ctl); + +	crtc_state->dpll_hw_state.pll8 = targ_cnt; + +	if (dcoampovr_en_h) +		crtc_state->dpll_hw_state.pll10 = PORT_PLL_DCO_AMP_OVR_EN_H; + +	crtc_state->dpll_hw_state.pll10 |= PORT_PLL_DCO_AMP(dco_amp); + +	crtc_state->dpll_hw_state.pcsdw12 = +		LANESTAGGER_STRAP_OVRD | lanestagger; + +	pll = intel_get_shared_dpll(intel_crtc, crtc_state); +	if (pll == NULL) { +		DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", +			pipe_name(intel_crtc->pipe)); +		return false; +	} + +	/* shared DPLL id 0 is DPLL A */ +	crtc_state->ddi_pll_sel = pll->id; + +	return true; +} +  /*   * Tries to find a *shared* PLL for the CRTC and store it in   * intel_crtc->ddi_pll_sel. @@ -1228,6 +1505,9 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,  	if (IS_SKYLAKE(dev))  		return skl_ddi_pll_select(intel_crtc, crtc_state,  					  intel_encoder, clock); +	else if (IS_BROXTON(dev)) +		return bxt_ddi_pll_select(intel_crtc, crtc_state, +					  intel_encoder, clock);  	else  		return hsw_ddi_pll_select(intel_crtc, crtc_state,  					  intel_encoder, clock); @@ -1519,6 +1799,67 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)  			   TRANS_CLK_SEL_DISABLED);  } +void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, +			     enum port port, int type) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	const struct bxt_ddi_buf_trans *ddi_translations; +	u32 n_entries, i; +	uint32_t val; + +	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { +		n_entries = ARRAY_SIZE(bxt_ddi_translations_dp); +		ddi_translations = bxt_ddi_translations_dp; +	} else if (type == INTEL_OUTPUT_HDMI) { +		n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi); +		ddi_translations = bxt_ddi_translations_hdmi; +	} else { +		DRM_DEBUG_KMS("Vswing programming not done for encoder %d\n", +				type); +		return; +	} + +	/* Check if default value has to be used */ +	if (level >= n_entries || +	    (type == INTEL_OUTPUT_HDMI && level == HDMI_LEVEL_SHIFT_UNKNOWN)) { +		for (i = 0; i < n_entries; i++) { +			if (ddi_translations[i].default_index) { +				level = i; +				break; +			} +		} +	} + +	/* +	 * While we write to the group register to program all lanes at once we +	 * can read only lane registers and we pick lanes 0/1 for that. +	 */ +	val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); +	val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); +	I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); + +	val = I915_READ(BXT_PORT_TX_DW2_LN0(port)); +	val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); +	val |= ddi_translations[level].margin << MARGIN_000_SHIFT | +	       ddi_translations[level].scale << UNIQ_TRANS_SCALE_SHIFT; +	I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val); + +	val = I915_READ(BXT_PORT_TX_DW3_LN0(port)); +	val &= ~UNIQE_TRANGE_EN_METHOD; +	if (ddi_translations[level].enable) +		val |= UNIQE_TRANGE_EN_METHOD; +	I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val); + +	val = I915_READ(BXT_PORT_TX_DW4_LN0(port)); +	val &= ~DE_EMPHASIS; +	val |= ddi_translations[level].deemphasis << DEEMPH_SHIFT; +	I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val); + +	val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); +	val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; +	I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); +} +  static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)  {  	struct drm_encoder *encoder = &intel_encoder->base; @@ -1527,6 +1868,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)  	struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);  	enum port port = intel_ddi_get_encoder_port(intel_encoder);  	int type = intel_encoder->type; +	int hdmi_level;  	if (type == INTEL_OUTPUT_EDP) {  		struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1548,7 +1890,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)  			val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |  				 DPLL_CTRL1_SSC(dpll) | -				 DPLL_CRTL1_LINK_RATE_MASK(dpll)); +				 DPLL_CTRL1_LINK_RATE_MASK(dpll));  			val |= crtc->config->dpll_hw_state.ctrl1 << (dpll * 6);  			I915_WRITE(DPLL_CTRL1, val); @@ -1565,7 +1907,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)  		I915_WRITE(DPLL_CTRL2, val); -	} else { +	} else if (INTEL_INFO(dev)->gen < 9) {  		WARN_ON(crtc->config->ddi_pll_sel == PORT_CLK_SEL_NONE);  		I915_WRITE(PORT_CLK_SEL(port), crtc->config->ddi_pll_sel);  	} @@ -1583,6 +1925,12 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)  	} else if (type == INTEL_OUTPUT_HDMI) {  		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); +		if (IS_BROXTON(dev)) { +			hdmi_level = dev_priv->vbt. +				ddi_port_info[port].hdmi_level_shift; +			bxt_ddi_vswing_sequence(dev, hdmi_level, port, +					INTEL_OUTPUT_HDMI); +		}  		intel_hdmi->set_infoframes(encoder,  					   crtc->config->has_hdmi_sink,  					   &crtc->config->base.adjusted_mode); @@ -1624,7 +1972,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)  	if (IS_SKYLAKE(dev))  		I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) |  					DPLL_CTRL2_DDI_CLK_OFF(port))); -	else +	else if (INTEL_INFO(dev)->gen < 9)  		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);  } @@ -1689,105 +2037,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)  	}  } -static int skl_get_cdclk_freq(struct drm_i915_private *dev_priv) -{ -	uint32_t lcpll1 = I915_READ(LCPLL1_CTL); -	uint32_t cdctl = I915_READ(CDCLK_CTL); -	uint32_t linkrate; - -	if (!(lcpll1 & LCPLL_PLL_ENABLE)) { -		WARN(1, "LCPLL1 not enabled\n"); -		return 24000; /* 24MHz is the cd freq with NSSC ref */ -	} - -	if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) -		return 540000; - -	linkrate = (I915_READ(DPLL_CTRL1) & -		    DPLL_CRTL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; - -	if (linkrate == DPLL_CRTL1_LINK_RATE_2160 || -	    linkrate == DPLL_CRTL1_LINK_RATE_1080) { -		/* vco 8640 */ -		switch (cdctl & CDCLK_FREQ_SEL_MASK) { -		case CDCLK_FREQ_450_432: -			return 432000; -		case CDCLK_FREQ_337_308: -			return 308570; -		case CDCLK_FREQ_675_617: -			return 617140; -		default: -			WARN(1, "Unknown cd freq selection\n"); -		} -	} else { -		/* vco 8100 */ -		switch (cdctl & CDCLK_FREQ_SEL_MASK) { -		case CDCLK_FREQ_450_432: -			return 450000; -		case CDCLK_FREQ_337_308: -			return 337500; -		case CDCLK_FREQ_675_617: -			return 675000; -		default: -			WARN(1, "Unknown cd freq selection\n"); -		} -	} - -	/* error case, do as if DPLL0 isn't enabled */ -	return 24000; -} - -static int bdw_get_cdclk_freq(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 hsw_get_cdclk_freq(struct drm_i915_private *dev_priv) -{ -	struct drm_device *dev = dev_priv->dev; -	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)) -		return 337500; -	else -		return 540000; -} - -int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) -{ -	struct drm_device *dev = dev_priv->dev; - -	if (IS_SKYLAKE(dev)) -		return skl_get_cdclk_freq(dev_priv); - -	if (IS_BROADWELL(dev)) -		return bdw_get_cdclk_freq(dev_priv); - -	/* Haswell */ -	return hsw_get_cdclk_freq(dev_priv); -} -  static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,  			       struct intel_shared_dpll *pll)  { @@ -1887,7 +2136,7 @@ static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,  	val = I915_READ(DPLL_CTRL1);  	val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | -		 DPLL_CRTL1_LINK_RATE_MASK(dpll)); +		 DPLL_CTRL1_LINK_RATE_MASK(dpll));  	val |= pll->config.hw_state.ctrl1 << (dpll * 6);  	I915_WRITE(DPLL_CTRL1, val); @@ -1963,22 +2212,325 @@ static void skl_shared_dplls_init(struct drm_i915_private *dev_priv)  	}  } +static void broxton_phy_init(struct drm_i915_private *dev_priv, +			     enum dpio_phy phy) +{ +	enum port port; +	uint32_t val; + +	val = I915_READ(BXT_P_CR_GT_DISP_PWRON); +	val |= GT_DISPLAY_POWER_ON(phy); +	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); + +	/* Considering 10ms timeout until BSpec is updated */ +	if (wait_for(I915_READ(BXT_PORT_CL1CM_DW0(phy)) & PHY_POWER_GOOD, 10)) +		DRM_ERROR("timeout during PHY%d power on\n", phy); + +	for (port =  (phy == DPIO_PHY0 ? PORT_B : PORT_A); +	     port <= (phy == DPIO_PHY0 ? PORT_C : PORT_A); port++) { +		int lane; + +		for (lane = 0; lane < 4; lane++) { +			val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); +			/* +			 * Note that on CHV this flag is called UPAR, but has +			 * the same function. +			 */ +			val &= ~LATENCY_OPTIM; +			if (lane != 1) +				val |= LATENCY_OPTIM; + +			I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val); +		} +	} + +	/* Program PLL Rcomp code offset */ +	val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); +	val &= ~IREF0RC_OFFSET_MASK; +	val |= 0xE4 << IREF0RC_OFFSET_SHIFT; +	I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val); + +	val = I915_READ(BXT_PORT_CL1CM_DW10(phy)); +	val &= ~IREF1RC_OFFSET_MASK; +	val |= 0xE4 << IREF1RC_OFFSET_SHIFT; +	I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val); + +	/* Program power gating */ +	val = I915_READ(BXT_PORT_CL1CM_DW28(phy)); +	val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | +		SUS_CLK_CONFIG; +	I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val); + +	if (phy == DPIO_PHY0) { +		val = I915_READ(BXT_PORT_CL2CM_DW6_BC); +		val |= DW6_OLDO_DYN_PWR_DOWN_EN; +		I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val); +	} + +	val = I915_READ(BXT_PORT_CL1CM_DW30(phy)); +	val &= ~OCL2_LDOFUSE_PWR_DIS; +	/* +	 * On PHY1 disable power on the second channel, since no port is +	 * connected there. On PHY0 both channels have a port, so leave it +	 * enabled. +	 * TODO: port C is only connected on BXT-P, so on BXT0/1 we should +	 * power down the second channel on PHY0 as well. +	 */ +	if (phy == DPIO_PHY1) +		val |= OCL2_LDOFUSE_PWR_DIS; +	I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); + +	if (phy == DPIO_PHY0) { +		uint32_t grc_code; +		/* +		 * PHY0 isn't connected to an RCOMP resistor so copy over +		 * the corresponding calibrated value from PHY1, and disable +		 * the automatic calibration on PHY0. +		 */ +		if (wait_for(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE, +			     10)) +			DRM_ERROR("timeout waiting for PHY1 GRC\n"); + +		val = I915_READ(BXT_PORT_REF_DW6(DPIO_PHY1)); +		val = (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; +		grc_code = val << GRC_CODE_FAST_SHIFT | +			   val << GRC_CODE_SLOW_SHIFT | +			   val; +		I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code); + +		val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0)); +		val |= GRC_DIS | GRC_RDY_OVRD; +		I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val); +	} + +	val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); +	val |= COMMON_RESET_DIS; +	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); +} + +void broxton_ddi_phy_init(struct drm_device *dev) +{ +	/* Enable PHY1 first since it provides Rcomp for PHY0 */ +	broxton_phy_init(dev->dev_private, DPIO_PHY1); +	broxton_phy_init(dev->dev_private, DPIO_PHY0); +} + +static void broxton_phy_uninit(struct drm_i915_private *dev_priv, +			       enum dpio_phy phy) +{ +	uint32_t val; + +	val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); +	val &= ~COMMON_RESET_DIS; +	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); +} + +void broxton_ddi_phy_uninit(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	broxton_phy_uninit(dev_priv, DPIO_PHY1); +	broxton_phy_uninit(dev_priv, DPIO_PHY0); + +	/* FIXME: do this in broxton_phy_uninit per phy */ +	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, 0); +} + +static const char * const bxt_ddi_pll_names[] = { +	"PORT PLL A", +	"PORT PLL B", +	"PORT PLL C", +}; + +static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, +				struct intel_shared_dpll *pll) +{ +	uint32_t temp; +	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */ + +	temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); +	temp &= ~PORT_PLL_REF_SEL; +	/* Non-SSC reference */ +	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); + +	/* Disable 10 bit clock */ +	temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); +	temp &= ~PORT_PLL_10BIT_CLK_ENABLE; +	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + +	/* Write P1 & P2 */ +	temp = I915_READ(BXT_PORT_PLL_EBB_0(port)); +	temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK); +	temp |= pll->config.hw_state.ebb0; +	I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp); + +	/* Write M2 integer */ +	temp = I915_READ(BXT_PORT_PLL(port, 0)); +	temp &= ~PORT_PLL_M2_MASK; +	temp |= pll->config.hw_state.pll0; +	I915_WRITE(BXT_PORT_PLL(port, 0), temp); + +	/* Write N */ +	temp = I915_READ(BXT_PORT_PLL(port, 1)); +	temp &= ~PORT_PLL_N_MASK; +	temp |= pll->config.hw_state.pll1; +	I915_WRITE(BXT_PORT_PLL(port, 1), temp); + +	/* Write M2 fraction */ +	temp = I915_READ(BXT_PORT_PLL(port, 2)); +	temp &= ~PORT_PLL_M2_FRAC_MASK; +	temp |= pll->config.hw_state.pll2; +	I915_WRITE(BXT_PORT_PLL(port, 2), temp); + +	/* Write M2 fraction enable */ +	temp = I915_READ(BXT_PORT_PLL(port, 3)); +	temp &= ~PORT_PLL_M2_FRAC_ENABLE; +	temp |= pll->config.hw_state.pll3; +	I915_WRITE(BXT_PORT_PLL(port, 3), temp); + +	/* Write coeff */ +	temp = I915_READ(BXT_PORT_PLL(port, 6)); +	temp &= ~PORT_PLL_PROP_COEFF_MASK; +	temp &= ~PORT_PLL_INT_COEFF_MASK; +	temp &= ~PORT_PLL_GAIN_CTL_MASK; +	temp |= pll->config.hw_state.pll6; +	I915_WRITE(BXT_PORT_PLL(port, 6), temp); + +	/* Write calibration val */ +	temp = I915_READ(BXT_PORT_PLL(port, 8)); +	temp &= ~PORT_PLL_TARGET_CNT_MASK; +	temp |= pll->config.hw_state.pll8; +	I915_WRITE(BXT_PORT_PLL(port, 8), temp); + +	temp = I915_READ(BXT_PORT_PLL(port, 9)); +	temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK; +	temp |= (5 << 1); +	I915_WRITE(BXT_PORT_PLL(port, 9), temp); + +	temp = I915_READ(BXT_PORT_PLL(port, 10)); +	temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H; +	temp &= ~PORT_PLL_DCO_AMP_MASK; +	temp |= pll->config.hw_state.pll10; +	I915_WRITE(BXT_PORT_PLL(port, 10), temp); + +	/* Recalibrate with new settings */ +	temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); +	temp |= PORT_PLL_RECALIBRATE; +	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); +	/* Enable 10 bit clock */ +	temp |= PORT_PLL_10BIT_CLK_ENABLE; +	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + +	/* Enable PLL */ +	temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); +	temp |= PORT_PLL_ENABLE; +	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); +	POSTING_READ(BXT_PORT_PLL_ENABLE(port)); + +	if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & +			PORT_PLL_LOCK), 200)) +		DRM_ERROR("PLL %d not locked\n", port); + +	/* +	 * While we write to the group register to program all lanes at once we +	 * can read only lane registers and we pick lanes 0/1 for that. +	 */ +	temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); +	temp &= ~LANE_STAGGER_MASK; +	temp &= ~LANESTAGGER_STRAP_OVRD; +	temp |= pll->config.hw_state.pcsdw12; +	I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp); +} + +static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, +					struct intel_shared_dpll *pll) +{ +	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */ +	uint32_t temp; + +	temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); +	temp &= ~PORT_PLL_ENABLE; +	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); +	POSTING_READ(BXT_PORT_PLL_ENABLE(port)); +} + +static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, +					struct intel_shared_dpll *pll, +					struct intel_dpll_hw_state *hw_state) +{ +	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */ +	uint32_t val; + +	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) +		return false; + +	val = I915_READ(BXT_PORT_PLL_ENABLE(port)); +	if (!(val & PORT_PLL_ENABLE)) +		return false; + +	hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); +	hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); +	hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); +	hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); +	hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); +	hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); +	hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); +	hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10)); +	/* +	 * While we write to the group register to program all lanes at once we +	 * can read only lane registers. We configure all lanes the same way, so +	 * here just read out lanes 0/1 and output a note if lanes 2/3 differ. +	 */ +	hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); +	if (I915_READ(BXT_PORT_PCS_DW12_LN23(port) != hw_state->pcsdw12)) +		DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", +				 hw_state->pcsdw12, +				 I915_READ(BXT_PORT_PCS_DW12_LN23(port))); + +	return true; +} + +static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv) +{ +	int i; + +	dev_priv->num_shared_dpll = 3; + +	for (i = 0; i < dev_priv->num_shared_dpll; i++) { +		dev_priv->shared_dplls[i].id = i; +		dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i]; +		dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable; +		dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable; +		dev_priv->shared_dplls[i].get_hw_state = +			bxt_ddi_pll_get_hw_state; +	} +} +  void intel_ddi_pll_init(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	uint32_t val = I915_READ(LCPLL_CTL); +	int cdclk_freq;  	if (IS_SKYLAKE(dev))  		skl_shared_dplls_init(dev_priv); +	else if (IS_BROXTON(dev)) +		bxt_shared_dplls_init(dev_priv);  	else  		hsw_shared_dplls_init(dev_priv); -	DRM_DEBUG_KMS("CDCLK running at %dKHz\n", -		      intel_ddi_get_cdclk_freq(dev_priv)); +	cdclk_freq = dev_priv->display.get_display_clock_speed(dev); +	DRM_DEBUG_KMS("CDCLK running at %dKHz\n", cdclk_freq);  	if (IS_SKYLAKE(dev)) { +		dev_priv->skl_boot_cdclk = cdclk_freq;  		if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))  			DRM_ERROR("LCPLL1 is disabled\n"); +		else +			intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); +	} else if (IS_BROXTON(dev)) { +		broxton_init_cdclk(dev); +		broxton_ddi_phy_init(dev);  	} else {  		/*  		 * The LCPLL register should be turned on by the BIOS. For now | 
