diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 607 | 
1 files changed, 453 insertions, 154 deletions
| diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d0237102c27e..76afc62373d7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -41,6 +41,12 @@  #define DP_LINK_CHECK_TIMEOUT	(10 * 1000) +/* Compliance test status bits  */ +#define INTEL_DP_RESOLUTION_SHIFT_MASK	0 +#define INTEL_DP_RESOLUTION_PREFERRED	(1 << INTEL_DP_RESOLUTION_SHIFT_MASK) +#define INTEL_DP_RESOLUTION_STANDARD	(2 << INTEL_DP_RESOLUTION_SHIFT_MASK) +#define INTEL_DP_RESOLUTION_FAILSAFE	(3 << INTEL_DP_RESOLUTION_SHIFT_MASK) +  struct dp_link_dpll {  	int link_bw;  	struct dpll dpll; @@ -84,8 +90,8 @@ static const struct dp_link_dpll chv_dpll[] = {  	{ DP_LINK_BW_5_4,	/* m2_int = 27, m2_fraction = 0 */  		{ .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }  }; -/* Skylake supports following rates */ -static const int gen9_rates[] = { 162000, 216000, 270000, + +static const int skl_rates[] = { 162000, 216000, 270000,  				  324000, 432000, 540000 };  static const int chv_rates[] = { 162000, 202500, 210000, 216000,  				 243000, 270000, 324000, 405000, @@ -696,15 +702,13 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  {  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	struct drm_device *dev = intel_dig_port->base.base.dev; +	struct drm_i915_private *dev_priv = dev->dev_private;  	if (index)  		return 0;  	if (intel_dig_port->port == PORT_A) { -		if (IS_GEN6(dev) || IS_GEN7(dev)) -			return 200; /* SNB & IVB eDP input clock at 400Mhz */ -		else -			return 225; /* eDP input clock at 450Mhz */ +		return DIV_ROUND_UP(dev_priv->display.get_display_clock_speed(dev), 2000);  	} else {  		return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);  	} @@ -719,7 +723,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  	if (intel_dig_port->port == PORT_A) {  		if (index)  			return 0; -		return DIV_ROUND_CLOSEST(intel_ddi_get_cdclk_freq(dev_priv), 2000); +		return DIV_ROUND_CLOSEST(dev_priv->display.get_display_clock_speed(dev), 2000);  	} else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {  		/* Workaround for non-ULT HSW */  		switch (index) { @@ -876,14 +880,21 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  				   DP_AUX_CH_CTL_TIME_OUT_ERROR |  				   DP_AUX_CH_CTL_RECEIVE_ERROR); -			if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | -				      DP_AUX_CH_CTL_RECEIVE_ERROR)) +			if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) +				continue; + +			/* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2 +			 *   400us delay required for errors and timeouts +			 *   Timeout errors from the HW already meet this +			 *   requirement so skip to next iteration +			 */ +			if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { +				usleep_range(400, 500);  				continue; +			}  			if (status & DP_AUX_CH_CTL_DONE) -				break; +				goto done;  		} -		if (status & DP_AUX_CH_CTL_DONE) -			break;  	}  	if ((status & DP_AUX_CH_CTL_DONE) == 0) { @@ -892,6 +903,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  		goto out;  	} +done:  	/* Check for timeout or receive error.  	 * Timeouts occur when the sink is not connected  	 */ @@ -1084,6 +1096,9 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)  {  	u32 ctrl1; +	memset(&pipe_config->dpll_hw_state, 0, +	       sizeof(pipe_config->dpll_hw_state)); +  	pipe_config->ddi_pll_sel = SKL_DPLL0;  	pipe_config->dpll_hw_state.cfgcr1 = 0;  	pipe_config->dpll_hw_state.cfgcr2 = 0; @@ -1091,30 +1106,30 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)  	ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);  	switch (link_clock / 2) {  	case 81000: -		ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_810, +		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,  					      SKL_DPLL0);  		break;  	case 135000: -		ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1350, +		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350,  					      SKL_DPLL0);  		break;  	case 270000: -		ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_2700, +		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700,  					      SKL_DPLL0);  		break;  	case 162000: -		ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1620, +		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620,  					      SKL_DPLL0);  		break;  	/* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which  	results in CDCLK change. Need to handle the change of CDCLK by  	disabling pipes and re-enabling them */  	case 108000: -		ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1080, +		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,  					      SKL_DPLL0);  		break;  	case 216000: -		ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_2160, +		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160,  					      SKL_DPLL0);  		break; @@ -1154,9 +1169,9 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)  static int  intel_dp_source_rates(struct drm_device *dev, const int **source_rates)  { -	if (INTEL_INFO(dev)->gen >= 9) { -		*source_rates = gen9_rates; -		return ARRAY_SIZE(gen9_rates); +	if (IS_SKYLAKE(dev)) { +		*source_rates = skl_rates; +		return ARRAY_SIZE(skl_rates);  	} else if (IS_CHERRYVIEW(dev)) {  		*source_rates = chv_rates;  		return ARRAY_SIZE(chv_rates); @@ -1253,7 +1268,7 @@ static void snprintf_int_array(char *str, size_t len,  	str[0] = '\0';  	for (i = 0; i < nelem; i++) { -		int r = snprintf(str, len, "%d,", array[i]); +		int r = snprintf(str, len, "%s%d", i ? ", " : "", array[i]);  		if (r >= len)  			return;  		str += r; @@ -1348,11 +1363,19 @@ intel_dp_compute_config(struct intel_encoder *encoder,  	pipe_config->has_dp_encoder = true;  	pipe_config->has_drrs = false; -	pipe_config->has_audio = intel_dp->has_audio; +	pipe_config->has_audio = intel_dp->has_audio && port != PORT_A;  	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {  		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,  				       adjusted_mode); + +		if (INTEL_INFO(dev)->gen >= 9) { +			int ret; +			ret = skl_update_scaler_users(intel_crtc, pipe_config, NULL, NULL, 0); +			if (ret) +				return ret; +		} +  		if (!HAS_PCH_SPLIT(dev))  			intel_gmch_panel_fitting(intel_crtc, pipe_config,  						 intel_connector->panel.fitting_mode); @@ -1465,6 +1488,8 @@ found:  	if (IS_SKYLAKE(dev) && is_edp(intel_dp))  		skl_edp_set_pll_config(pipe_config, common_rates[clock]); +	else if (IS_BROXTON(dev)) +		/* handled in ddi */;  	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))  		hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);  	else @@ -1544,7 +1569,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder)  	/* Split out the IBX/CPU vs CPT settings */ -	if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { +	if (IS_GEN7(dev) && port == PORT_A) {  		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)  			intel_dp->DP |= DP_SYNC_HS_HIGH;  		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) @@ -1555,7 +1580,18 @@ static void intel_dp_prepare(struct intel_encoder *encoder)  			intel_dp->DP |= DP_ENHANCED_FRAMING;  		intel_dp->DP |= crtc->pipe << 29; -	} else if (!HAS_PCH_CPT(dev) || port == PORT_A) { +	} else if (HAS_PCH_CPT(dev) && port != PORT_A) { +		u32 trans_dp; + +		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; + +		trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe)); +		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) +			trans_dp |= TRANS_DP_ENH_FRAMING; +		else +			trans_dp &= ~TRANS_DP_ENH_FRAMING; +		I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); +	} else {  		if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))  			intel_dp->DP |= intel_dp->color_range; @@ -1568,14 +1604,10 @@ static void intel_dp_prepare(struct intel_encoder *encoder)  		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))  			intel_dp->DP |= DP_ENHANCED_FRAMING; -		if (!IS_CHERRYVIEW(dev)) { -			if (crtc->pipe == 1) -				intel_dp->DP |= DP_PIPEB_SELECT; -		} else { +		if (IS_CHERRYVIEW(dev))  			intel_dp->DP |= DP_PIPE_SELECT_CHV(crtc->pipe); -		} -	} else { -		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; +		else if (crtc->pipe == PIPE_B) +			intel_dp->DP |= DP_PIPEB_SELECT;  	}  } @@ -2159,41 +2191,25 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,  	if (!(tmp & DP_PORT_EN))  		return false; -	if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { +	if (IS_GEN7(dev) && port == PORT_A) {  		*pipe = PORT_TO_PIPE_CPT(tmp); -	} else if (IS_CHERRYVIEW(dev)) { -		*pipe = DP_PORT_TO_PIPE_CHV(tmp); -	} else if (!HAS_PCH_CPT(dev) || port == PORT_A) { -		*pipe = PORT_TO_PIPE(tmp); -	} else { -		u32 trans_sel; -		u32 trans_dp; -		int i; +	} else if (HAS_PCH_CPT(dev) && port != PORT_A) { +		enum pipe p; -		switch (intel_dp->output_reg) { -		case PCH_DP_B: -			trans_sel = TRANS_DP_PORT_SEL_B; -			break; -		case PCH_DP_C: -			trans_sel = TRANS_DP_PORT_SEL_C; -			break; -		case PCH_DP_D: -			trans_sel = TRANS_DP_PORT_SEL_D; -			break; -		default: -			return true; -		} - -		for_each_pipe(dev_priv, i) { -			trans_dp = I915_READ(TRANS_DP_CTL(i)); -			if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) { -				*pipe = i; +		for_each_pipe(dev_priv, p) { +			u32 trans_dp = I915_READ(TRANS_DP_CTL(p)); +			if (TRANS_DP_PIPE_TO_PORT(trans_dp) == port) { +				*pipe = p;  				return true;  			}  		}  		DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n",  			      intel_dp->output_reg); +	} else if (IS_CHERRYVIEW(dev)) { +		*pipe = DP_PORT_TO_PIPE_CHV(tmp); +	} else { +		*pipe = PORT_TO_PIPE(tmp);  	}  	return true; @@ -2211,27 +2227,27 @@ static void intel_dp_get_config(struct intel_encoder *encoder,  	int dotclock;  	tmp = I915_READ(intel_dp->output_reg); -	if (tmp & DP_AUDIO_OUTPUT_ENABLE) -		pipe_config->has_audio = true; -	if ((port == PORT_A) || !HAS_PCH_CPT(dev)) { -		if (tmp & DP_SYNC_HS_HIGH) +	pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A; + +	if (HAS_PCH_CPT(dev) && port != PORT_A) { +		tmp = I915_READ(TRANS_DP_CTL(crtc->pipe)); +		if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH)  			flags |= DRM_MODE_FLAG_PHSYNC;  		else  			flags |= DRM_MODE_FLAG_NHSYNC; -		if (tmp & DP_SYNC_VS_HIGH) +		if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH)  			flags |= DRM_MODE_FLAG_PVSYNC;  		else  			flags |= DRM_MODE_FLAG_NVSYNC;  	} else { -		tmp = I915_READ(TRANS_DP_CTL(crtc->pipe)); -		if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH) +		if (tmp & DP_SYNC_HS_HIGH)  			flags |= DRM_MODE_FLAG_PHSYNC;  		else  			flags |= DRM_MODE_FLAG_NHSYNC; -		if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH) +		if (tmp & DP_SYNC_VS_HIGH)  			flags |= DRM_MODE_FLAG_PVSYNC;  		else  			flags |= DRM_MODE_FLAG_NVSYNC; @@ -2338,7 +2354,7 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)  	intel_dp_link_down(intel_dp); -	mutex_lock(&dev_priv->dpio_lock); +	mutex_lock(&dev_priv->sb_lock);  	/* Propagate soft reset to data lane reset */  	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); @@ -2357,7 +2373,7 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)  	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);  	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); -	mutex_unlock(&dev_priv->dpio_lock); +	mutex_unlock(&dev_priv->sb_lock);  }  static void @@ -2396,7 +2412,8 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,  		}  		I915_WRITE(DP_TP_CTL(port), temp); -	} else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { +	} else if ((IS_GEN7(dev) && port == PORT_A) || +		   (HAS_PCH_CPT(dev) && port != PORT_A)) {  		*DP &= ~DP_LINK_TRAIN_MASK_CPT;  		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { @@ -2474,6 +2491,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);  	uint32_t dp_reg = I915_READ(intel_dp->output_reg); +	unsigned int lane_mask = 0x0;  	if (WARN_ON(dp_reg & DP_PORT_EN))  		return; @@ -2492,7 +2510,8 @@ static void intel_enable_dp(struct intel_encoder *encoder)  	pps_unlock(intel_dp);  	if (IS_VALLEYVIEW(dev)) -		vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp)); +		vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp), +				    lane_mask);  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);  	intel_dp_start_link_train(intel_dp); @@ -2651,7 +2670,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)  	int pipe = intel_crtc->pipe;  	u32 val; -	mutex_lock(&dev_priv->dpio_lock); +	mutex_lock(&dev_priv->sb_lock);  	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));  	val = 0; @@ -2664,7 +2683,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888); -	mutex_unlock(&dev_priv->dpio_lock); +	mutex_unlock(&dev_priv->sb_lock);  	intel_enable_dp(encoder);  } @@ -2682,7 +2701,7 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)  	intel_dp_prepare(encoder);  	/* Program Tx lane resets to default */ -	mutex_lock(&dev_priv->dpio_lock); +	mutex_lock(&dev_priv->sb_lock);  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),  			 DPIO_PCS_TX_LANE2_RESET |  			 DPIO_PCS_TX_LANE1_RESET); @@ -2696,7 +2715,7 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000); -	mutex_unlock(&dev_priv->dpio_lock); +	mutex_unlock(&dev_priv->sb_lock);  }  static void chv_pre_enable_dp(struct intel_encoder *encoder) @@ -2709,10 +2728,10 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)  		to_intel_crtc(encoder->base.crtc);  	enum dpio_channel ch = vlv_dport_to_channel(dport);  	int pipe = intel_crtc->pipe; -	int data, i; +	int data, i, stagger;  	u32 val; -	mutex_lock(&dev_priv->dpio_lock); +	mutex_lock(&dev_priv->sb_lock);  	/* allow hardware to manage TX FIFO reset source */  	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); @@ -2749,9 +2768,40 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)  	}  	/* Data lane stagger programming */ -	/* FIXME: Fix up value only after power analysis */ +	if (intel_crtc->config->port_clock > 270000) +		stagger = 0x18; +	else if (intel_crtc->config->port_clock > 135000) +		stagger = 0xd; +	else if (intel_crtc->config->port_clock > 67500) +		stagger = 0x7; +	else if (intel_crtc->config->port_clock > 33750) +		stagger = 0x4; +	else +		stagger = 0x2; + +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); +	val |= DPIO_TX2_STAGGER_MASK(0x1f); +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); -	mutex_unlock(&dev_priv->dpio_lock); +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); +	val |= DPIO_TX2_STAGGER_MASK(0x1f); +	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); + +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch), +		       DPIO_LANESTAGGER_STRAP(stagger) | +		       DPIO_LANESTAGGER_STRAP_OVRD | +		       DPIO_TX1_STAGGER_MASK(0x1f) | +		       DPIO_TX1_STAGGER_MULT(6) | +		       DPIO_TX2_STAGGER_MULT(0)); + +	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch), +		       DPIO_LANESTAGGER_STRAP(stagger) | +		       DPIO_LANESTAGGER_STRAP_OVRD | +		       DPIO_TX1_STAGGER_MASK(0x1f) | +		       DPIO_TX1_STAGGER_MULT(7) | +		       DPIO_TX2_STAGGER_MULT(5)); + +	mutex_unlock(&dev_priv->sb_lock);  	intel_enable_dp(encoder);  } @@ -2769,7 +2819,7 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)  	intel_dp_prepare(encoder); -	mutex_lock(&dev_priv->dpio_lock); +	mutex_lock(&dev_priv->sb_lock);  	/* program left/right clock distribution */  	if (pipe != PIPE_B) { @@ -2819,7 +2869,7 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)  		val |= CHV_CMN_USEDCLKCHANNEL;  	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val); -	mutex_unlock(&dev_priv->dpio_lock); +	mutex_unlock(&dev_priv->sb_lock);  }  /* @@ -2874,8 +2924,10 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)  	struct drm_i915_private *dev_priv = dev->dev_private;  	enum port port = dp_to_dig_port(intel_dp)->port; -	if (INTEL_INFO(dev)->gen >= 9) { -		if (dev_priv->vbt.edp_low_vswing && port == PORT_A) +	if (IS_BROXTON(dev)) +		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; +	else if (INTEL_INFO(dev)->gen >= 9) { +		if (dev_priv->edp_low_vswing && port == PORT_A)  			return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;  		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;  	} else if (IS_VALLEYVIEW(dev)) @@ -2956,7 +3008,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)  	}  } -static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) +static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)  {  	struct drm_device *dev = intel_dp_to_dev(intel_dp);  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -3042,7 +3094,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)  		return 0;  	} -	mutex_lock(&dev_priv->dpio_lock); +	mutex_lock(&dev_priv->sb_lock);  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000);  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value);  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), @@ -3051,12 +3103,12 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value);  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x80000000); -	mutex_unlock(&dev_priv->dpio_lock); +	mutex_unlock(&dev_priv->sb_lock);  	return 0;  } -static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp) +static uint32_t chv_signal_levels(struct intel_dp *intel_dp)  {  	struct drm_device *dev = intel_dp_to_dev(intel_dp);  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -3138,7 +3190,7 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp)  		return 0;  	} -	mutex_lock(&dev_priv->dpio_lock); +	mutex_lock(&dev_priv->sb_lock);  	/* Clear calc init */  	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); @@ -3225,7 +3277,7 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp)  	val |= DPIO_LRC_BYPASS;  	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, val); -	mutex_unlock(&dev_priv->dpio_lock); +	mutex_unlock(&dev_priv->sb_lock);  	return 0;  } @@ -3263,7 +3315,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp,  }  static uint32_t -intel_gen4_signal_levels(uint8_t train_set) +gen4_signal_levels(uint8_t train_set)  {  	uint32_t	signal_levels = 0; @@ -3302,7 +3354,7 @@ intel_gen4_signal_levels(uint8_t train_set)  /* Gen6's DP voltage swing and pre-emphasis control */  static uint32_t -intel_gen6_edp_signal_levels(uint8_t train_set) +gen6_edp_signal_levels(uint8_t train_set)  {  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3330,7 +3382,7 @@ intel_gen6_edp_signal_levels(uint8_t train_set)  /* Gen7's DP voltage swing and pre-emphasis control */  static uint32_t -intel_gen7_edp_signal_levels(uint8_t train_set) +gen7_edp_signal_levels(uint8_t train_set)  {  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3361,7 +3413,7 @@ intel_gen7_edp_signal_levels(uint8_t train_set)  /* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */  static uint32_t -intel_hsw_signal_levels(uint8_t train_set) +hsw_signal_levels(uint8_t train_set)  {  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3396,6 +3448,55 @@ intel_hsw_signal_levels(uint8_t train_set)  	}  } +static void bxt_signal_levels(struct intel_dp *intel_dp) +{ +	struct intel_digital_port *dport = dp_to_dig_port(intel_dp); +	enum port port = dport->port; +	struct drm_device *dev = dport->base.base.dev; +	struct intel_encoder *encoder = &dport->base; +	uint8_t train_set = intel_dp->train_set[0]; +	uint32_t level = 0; + +	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | +					 DP_TRAIN_PRE_EMPHASIS_MASK); +	switch (signal_levels) { +	default: +		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n"); +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: +		level = 0; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: +		level = 1; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: +		level = 2; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: +		level = 3; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: +		level = 4; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: +		level = 5; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: +		level = 6; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: +		level = 7; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: +		level = 8; +		break; +	case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: +		level = 9; +		break; +	} + +	bxt_ddi_vswing_sequence(dev, level, port, encoder->type); +} +  /* Properly updates "DP" with the correct signal levels. */  static void  intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) @@ -3406,27 +3507,38 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)  	uint32_t signal_levels, mask;  	uint8_t train_set = intel_dp->train_set[0]; -	if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) { -		signal_levels = intel_hsw_signal_levels(train_set); +	if (IS_BROXTON(dev)) { +		signal_levels = 0; +		bxt_signal_levels(intel_dp); +		mask = 0; +	} else if (HAS_DDI(dev)) { +		signal_levels = hsw_signal_levels(train_set);  		mask = DDI_BUF_EMP_MASK;  	} else if (IS_CHERRYVIEW(dev)) { -		signal_levels = intel_chv_signal_levels(intel_dp); +		signal_levels = chv_signal_levels(intel_dp);  		mask = 0;  	} else if (IS_VALLEYVIEW(dev)) { -		signal_levels = intel_vlv_signal_levels(intel_dp); +		signal_levels = vlv_signal_levels(intel_dp);  		mask = 0;  	} else if (IS_GEN7(dev) && port == PORT_A) { -		signal_levels = intel_gen7_edp_signal_levels(train_set); +		signal_levels = gen7_edp_signal_levels(train_set);  		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;  	} else if (IS_GEN6(dev) && port == PORT_A) { -		signal_levels = intel_gen6_edp_signal_levels(train_set); +		signal_levels = gen6_edp_signal_levels(train_set);  		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;  	} else { -		signal_levels = intel_gen4_signal_levels(train_set); +		signal_levels = gen4_signal_levels(train_set);  		mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK;  	} -	DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels); +	if (mask) +		DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels); + +	DRM_DEBUG_KMS("Using vswing level %d\n", +		train_set & DP_TRAIN_VOLTAGE_SWING_MASK); +	DRM_DEBUG_KMS("Using pre-emphasis level %d\n", +		(train_set & DP_TRAIN_PRE_EMPHASIS_MASK) >> +			DP_TRAIN_PRE_EMPHASIS_SHIFT);  	*DP = (*DP & ~mask) | signal_levels;  } @@ -3468,7 +3580,8 @@ static bool  intel_dp_reset_link_train(struct intel_dp *intel_dp, uint32_t *DP,  			uint8_t dp_train_pat)  { -	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set)); +	if (!intel_dp->train_set_valid) +		memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));  	intel_dp_set_signal_levels(intel_dp, DP);  	return intel_dp_set_link_train(intel_dp, DP, dp_train_pat);  } @@ -3581,6 +3694,23 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  			break;  		} +		/* +		 * if we used previously trained voltage and pre-emphasis values +		 * and we don't get clock recovery, reset link training values +		 */ +		if (intel_dp->train_set_valid) { +			DRM_DEBUG_KMS("clock recovery not ok, reset"); +			/* clear the flag as we are not reusing train set */ +			intel_dp->train_set_valid = false; +			if (!intel_dp_reset_link_train(intel_dp, &DP, +						       DP_TRAINING_PATTERN_1 | +						       DP_LINK_SCRAMBLING_DISABLE)) { +				DRM_ERROR("failed to enable link training\n"); +				return; +			} +			continue; +		} +  		/* Check to see if we've tried the max voltage */  		for (i = 0; i < intel_dp->lane_count; i++)  			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) @@ -3658,6 +3788,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  		/* Make sure clock is still ok */  		if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { +			intel_dp->train_set_valid = false;  			intel_dp_start_link_train(intel_dp);  			intel_dp_set_link_train(intel_dp, &DP,  						training_pattern | @@ -3673,6 +3804,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  		/* Try 5 times, then try clock recovery if that fails */  		if (tries > 5) { +			intel_dp->train_set_valid = false;  			intel_dp_start_link_train(intel_dp);  			intel_dp_set_link_train(intel_dp, &DP,  						training_pattern | @@ -3694,9 +3826,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  	intel_dp->DP = DP; -	if (channel_eq) +	if (channel_eq) { +		intel_dp->train_set_valid = true;  		DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); - +	}  }  void intel_dp_stop_link_train(struct intel_dp *intel_dp) @@ -3709,6 +3842,7 @@ static void  intel_dp_link_down(struct intel_dp *intel_dp)  {  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); +	struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);  	enum port port = intel_dig_port->port;  	struct drm_device *dev = intel_dig_port->base.base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -3722,36 +3856,41 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	DRM_DEBUG_KMS("\n"); -	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { +	if ((IS_GEN7(dev) && port == PORT_A) || +	    (HAS_PCH_CPT(dev) && port != PORT_A)) {  		DP &= ~DP_LINK_TRAIN_MASK_CPT; -		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); +		DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;  	} else {  		if (IS_CHERRYVIEW(dev))  			DP &= ~DP_LINK_TRAIN_MASK_CHV;  		else  			DP &= ~DP_LINK_TRAIN_MASK; -		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); +		DP |= DP_LINK_TRAIN_PAT_IDLE;  	} +	I915_WRITE(intel_dp->output_reg, DP);  	POSTING_READ(intel_dp->output_reg); -	if (HAS_PCH_IBX(dev) && -	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { -		/* Hardware workaround: leaving our transcoder select -		 * set to transcoder B while it's off will prevent the -		 * corresponding HDMI output on transcoder A. -		 * -		 * Combine this with another hardware workaround: -		 * transcoder select bit can only be cleared while the -		 * port is enabled. -		 */ -		DP &= ~DP_PIPEB_SELECT; +	DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE); +	I915_WRITE(intel_dp->output_reg, DP); +	POSTING_READ(intel_dp->output_reg); + +	/* +	 * HW workaround for IBX, we need to move the port +	 * to transcoder A after disabling it to allow the +	 * matching HDMI port to be enabled on transcoder A. +	 */ +	if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) { +		/* always enable with pattern 1 (as per spec) */ +		DP &= ~(DP_PIPEB_SELECT | DP_LINK_TRAIN_MASK); +		DP |= DP_PORT_EN | DP_LINK_TRAIN_PAT_1; +		I915_WRITE(intel_dp->output_reg, DP); +		POSTING_READ(intel_dp->output_reg); + +		DP &= ~DP_PORT_EN;  		I915_WRITE(intel_dp->output_reg, DP);  		POSTING_READ(intel_dp->output_reg);  	} -	DP &= ~DP_AUDIO_OUTPUT_ENABLE; -	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); -	POSTING_READ(intel_dp->output_reg);  	msleep(intel_dp->panel_power_down_delay);  } @@ -3782,6 +3921,21 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)  			dev_priv->psr.sink_support = true;  			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");  		} + +		if (INTEL_INFO(dev)->gen >= 9 && +			(intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { +			uint8_t frame_sync_cap; + +			dev_priv->psr.sink_support = true; +			intel_dp_dpcd_read_wake(&intel_dp->aux, +					DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP, +					&frame_sync_cap, 1); +			dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false; +			/* PSR2 needs frame sync as well */ +			dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync; +			DRM_DEBUG_KMS("PSR2 %s on sink", +				dev_priv->psr.psr2_support ? "supported" : "not supported"); +		}  	}  	/* Training Pattern 3 support, both source and sink */ @@ -3812,7 +3966,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)  			if (val == 0)  				break; -			intel_dp->sink_rates[i] = val * 200; +			/* Value read is in kHz while drm clock is saved in deca-kHz */ +			intel_dp->sink_rates[i] = (val * 200) / 10;  		}  		intel_dp->num_sink_rates = i;  	} @@ -3885,46 +4040,70 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)  	u8 buf;  	int test_crc_count;  	int attempts = 6; +	int ret = 0; -	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) -		return -EIO; +	hsw_disable_ips(intel_crtc); -	if (!(buf & DP_TEST_CRC_SUPPORTED)) -		return -ENOTTY; +	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) { +		ret = -EIO; +		goto out; +	} -	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) -		return -EIO; +	if (!(buf & DP_TEST_CRC_SUPPORTED)) { +		ret = -ENOTTY; +		goto out; +	} + +	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) { +		ret = -EIO; +		goto out; +	}  	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, -				buf | DP_TEST_SINK_START) < 0) -		return -EIO; +				buf | DP_TEST_SINK_START) < 0) { +		ret = -EIO; +		goto out; +	} + +	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) { +		ret = -EIO; +		goto out; +	} -	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) -		return -EIO;  	test_crc_count = buf & DP_TEST_COUNT_MASK;  	do {  		if (drm_dp_dpcd_readb(&intel_dp->aux, -				      DP_TEST_SINK_MISC, &buf) < 0) -			return -EIO; +				      DP_TEST_SINK_MISC, &buf) < 0) { +			ret = -EIO; +			goto out; +		}  		intel_wait_for_vblank(dev, intel_crtc->pipe);  	} while (--attempts && (buf & DP_TEST_COUNT_MASK) == test_crc_count);  	if (attempts == 0) {  		DRM_DEBUG_KMS("Panel is unable to calculate CRC after 6 vblanks\n"); -		return -ETIMEDOUT; +		ret = -ETIMEDOUT; +		goto out;  	} -	if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) -		return -EIO; +	if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) { +		ret = -EIO; +		goto out; +	} -	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) -		return -EIO; +	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) { +		ret = -EIO; +		goto out; +	}  	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, -			       buf & ~DP_TEST_SINK_START) < 0) -		return -EIO; - -	return 0; +			       buf & ~DP_TEST_SINK_START) < 0) { +		ret = -EIO; +		goto out; +	} +out: +	hsw_enable_ips(intel_crtc); +	return ret;  }  static bool @@ -3949,11 +4128,114 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)  	return true;  } -static void -intel_dp_handle_test_request(struct intel_dp *intel_dp) +static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)  { -	/* NAK by default */ -	drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, DP_TEST_NAK); +	uint8_t test_result = DP_TEST_ACK; +	return test_result; +} + +static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp) +{ +	uint8_t test_result = DP_TEST_NAK; +	return test_result; +} + +static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp) +{ +	uint8_t test_result = DP_TEST_NAK; +	struct intel_connector *intel_connector = intel_dp->attached_connector; +	struct drm_connector *connector = &intel_connector->base; + +	if (intel_connector->detect_edid == NULL || +	    connector->edid_corrupt || +	    intel_dp->aux.i2c_defer_count > 6) { +		/* Check EDID read for NACKs, DEFERs and corruption +		 * (DP CTS 1.2 Core r1.1) +		 *    4.2.2.4 : Failed EDID read, I2C_NAK +		 *    4.2.2.5 : Failed EDID read, I2C_DEFER +		 *    4.2.2.6 : EDID corruption detected +		 * Use failsafe mode for all cases +		 */ +		if (intel_dp->aux.i2c_nack_count > 0 || +			intel_dp->aux.i2c_defer_count > 0) +			DRM_DEBUG_KMS("EDID read had %d NACKs, %d DEFERs\n", +				      intel_dp->aux.i2c_nack_count, +				      intel_dp->aux.i2c_defer_count); +		intel_dp->compliance_test_data = INTEL_DP_RESOLUTION_FAILSAFE; +	} else { +		if (!drm_dp_dpcd_write(&intel_dp->aux, +					DP_TEST_EDID_CHECKSUM, +					&intel_connector->detect_edid->checksum, +					1)) +			DRM_DEBUG_KMS("Failed to write EDID checksum\n"); + +		test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE; +		intel_dp->compliance_test_data = INTEL_DP_RESOLUTION_STANDARD; +	} + +	/* Set test active flag here so userspace doesn't interrupt things */ +	intel_dp->compliance_test_active = 1; + +	return test_result; +} + +static uint8_t intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp) +{ +	uint8_t test_result = DP_TEST_NAK; +	return test_result; +} + +static void intel_dp_handle_test_request(struct intel_dp *intel_dp) +{ +	uint8_t response = DP_TEST_NAK; +	uint8_t rxdata = 0; +	int status = 0; + +	intel_dp->compliance_test_active = 0; +	intel_dp->compliance_test_type = 0; +	intel_dp->compliance_test_data = 0; + +	intel_dp->aux.i2c_nack_count = 0; +	intel_dp->aux.i2c_defer_count = 0; + +	status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_REQUEST, &rxdata, 1); +	if (status <= 0) { +		DRM_DEBUG_KMS("Could not read test request from sink\n"); +		goto update_status; +	} + +	switch (rxdata) { +	case DP_TEST_LINK_TRAINING: +		DRM_DEBUG_KMS("LINK_TRAINING test requested\n"); +		intel_dp->compliance_test_type = DP_TEST_LINK_TRAINING; +		response = intel_dp_autotest_link_training(intel_dp); +		break; +	case DP_TEST_LINK_VIDEO_PATTERN: +		DRM_DEBUG_KMS("TEST_PATTERN test requested\n"); +		intel_dp->compliance_test_type = DP_TEST_LINK_VIDEO_PATTERN; +		response = intel_dp_autotest_video_pattern(intel_dp); +		break; +	case DP_TEST_LINK_EDID_READ: +		DRM_DEBUG_KMS("EDID test requested\n"); +		intel_dp->compliance_test_type = DP_TEST_LINK_EDID_READ; +		response = intel_dp_autotest_edid(intel_dp); +		break; +	case DP_TEST_LINK_PHY_TEST_PATTERN: +		DRM_DEBUG_KMS("PHY_PATTERN test requested\n"); +		intel_dp->compliance_test_type = DP_TEST_LINK_PHY_TEST_PATTERN; +		response = intel_dp_autotest_phy_pattern(intel_dp); +		break; +	default: +		DRM_DEBUG_KMS("Invalid test request '%02x'\n", rxdata); +		break; +	} + +update_status: +	status = drm_dp_dpcd_write(&intel_dp->aux, +				   DP_TEST_RESPONSE, +				   &response, 1); +	if (status <= 0) +		DRM_DEBUG_KMS("Could not write test response to sink\n");  }  static int @@ -4059,7 +4341,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)  				   sink_irq_vector);  		if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST) -			intel_dp_handle_test_request(intel_dp); +			DRM_DEBUG_DRIVER("Test request in short pulse not handled\n");  		if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))  			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");  	} @@ -4289,6 +4571,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)  	enum drm_connector_status status;  	enum intel_display_power_domain power_domain;  	bool ret; +	u8 sink_irq_vector;  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",  		      connector->base.id, connector->name); @@ -4331,6 +4614,20 @@ intel_dp_detect(struct drm_connector *connector, bool force)  		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;  	status = connector_status_connected; +	/* Try to read the source of the interrupt */ +	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && +	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) { +		/* Clear interrupt source */ +		drm_dp_dpcd_writeb(&intel_dp->aux, +				   DP_DEVICE_SERVICE_IRQ_VECTOR, +				   sink_irq_vector); + +		if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST) +			intel_dp_handle_test_request(intel_dp); +		if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ)) +			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); +	} +  out:  	intel_dp_power_put(intel_dp, power_domain);  	return status; @@ -4661,6 +4958,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)  	intel_display_power_get(dev_priv, power_domain);  	if (long_hpd) { +		/* indicate that we need to restart link training */ +		intel_dp->train_set_valid = false;  		if (HAS_PCH_SPLIT(dev)) {  			if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) @@ -5539,12 +5838,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,  	intel_dp_aux_init(intel_dp, intel_connector);  	/* init MST on ports that can support it */ -	if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) { -		if (port == PORT_B || port == PORT_C || port == PORT_D) { -			intel_dp_mst_encoder_init(intel_dig_port, -						  intel_connector->base.base.id); -		} -	} +	if (HAS_DP_MST(dev) && +	    (port == PORT_B || port == PORT_C || port == PORT_D)) +		intel_dp_mst_encoder_init(intel_dig_port, +					  intel_connector->base.base.id);  	if (!intel_edp_init_connector(intel_dp, intel_connector)) {  		drm_dp_aux_unregister(&intel_dp->aux); @@ -5574,6 +5871,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,  		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);  	} +	i915_debugfs_connector_add(connector); +  	return true;  } | 
