diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 647 | 
1 files changed, 373 insertions, 274 deletions
| diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fdd2cbc56fa3..cf709835fb9a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -32,13 +32,12 @@  #include <linux/notifier.h>  #include <linux/reboot.h>  #include <asm/byteorder.h> -#include <drm/drmP.h>  #include <drm/drm_atomic_helper.h>  #include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h>  #include <drm/drm_dp_helper.h>  #include <drm/drm_edid.h>  #include <drm/drm_hdcp.h> +#include <drm/drm_probe_helper.h>  #include "intel_drv.h"  #include <drm/i915_drm.h>  #include "i915_drv.h" @@ -304,9 +303,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)  static int icl_max_source_rate(struct intel_dp *intel_dp)  {  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);  	enum port port = dig_port->base.port; -	if (port == PORT_B) +	if (intel_port_is_combophy(dev_priv, port) && +	    !intel_dp_is_edp(intel_dp))  		return 540000;  	return 810000; @@ -344,7 +345,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)  	if (INTEL_GEN(dev_priv) >= 10) {  		source_rates = cnl_rates;  		size = ARRAY_SIZE(cnl_rates); -		if (IS_GEN10(dev_priv)) +		if (IS_GEN(dev_priv, 10))  			max_rate = cnl_max_source_rate(intel_dp);  		else  			max_rate = icl_max_source_rate(intel_dp); @@ -428,7 +429,7 @@ static void intel_dp_set_common_rates(struct intel_dp *intel_dp)  }  static bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate, -				       uint8_t lane_count) +				       u8 lane_count)  {  	/*  	 * FIXME: we need to synchronize the current link parameters with @@ -448,7 +449,7 @@ static bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate,  static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,  						     int link_rate, -						     uint8_t lane_count) +						     u8 lane_count)  {  	const struct drm_display_mode *fixed_mode =  		intel_dp->attached_connector->panel.fixed_mode; @@ -463,7 +464,7 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,  }  int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, -					    int link_rate, uint8_t lane_count) +					    int link_rate, u8 lane_count)  {  	int index; @@ -571,19 +572,19 @@ intel_dp_mode_valid(struct drm_connector *connector,  	return MODE_OK;  } -uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes) +u32 intel_dp_pack_aux(const u8 *src, int src_bytes)  { -	int	i; -	uint32_t v = 0; +	int i; +	u32 v = 0;  	if (src_bytes > 4)  		src_bytes = 4;  	for (i = 0; i < src_bytes; i++) -		v |= ((uint32_t) src[i]) << ((3-i) * 8); +		v |= ((u32)src[i]) << ((3 - i) * 8);  	return v;  } -static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) +static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes)  {  	int i;  	if (dst_bytes > 4) @@ -600,30 +601,39 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,  static void  intel_dp_pps_init(struct intel_dp *intel_dp); -static void pps_lock(struct intel_dp *intel_dp) +static intel_wakeref_t +pps_lock(struct intel_dp *intel_dp)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +	intel_wakeref_t wakeref;  	/*  	 * See intel_power_sequencer_reset() why we need  	 * a power domain reference here.  	 */ -	intel_display_power_get(dev_priv, -				intel_aux_power_domain(dp_to_dig_port(intel_dp))); +	wakeref = intel_display_power_get(dev_priv, +					  intel_aux_power_domain(dp_to_dig_port(intel_dp)));  	mutex_lock(&dev_priv->pps_mutex); + +	return wakeref;  } -static void pps_unlock(struct intel_dp *intel_dp) +static intel_wakeref_t +pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	mutex_unlock(&dev_priv->pps_mutex); -  	intel_display_power_put(dev_priv, -				intel_aux_power_domain(dp_to_dig_port(intel_dp))); +				intel_aux_power_domain(dp_to_dig_port(intel_dp)), +				wakeref); +	return 0;  } +#define with_pps_lock(dp, wf) \ +	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf))) +  static void  vlv_power_sequencer_kick(struct intel_dp *intel_dp)  { @@ -633,7 +643,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)  	bool pll_enabled, release_cl_override = false;  	enum dpio_phy phy = DPIO_PHY(pipe);  	enum dpio_channel ch = vlv_pipe_to_channel(pipe); -	uint32_t DP; +	u32 DP;  	if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,  		 "skipping pipe %c power sequencer kick due to port %c being active\n", @@ -972,30 +982,29 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,  	struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),  						 edp_notifier);  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +	intel_wakeref_t wakeref;  	if (!intel_dp_is_edp(intel_dp) || code != SYS_RESTART)  		return 0; -	pps_lock(intel_dp); - -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); -		i915_reg_t pp_ctrl_reg, pp_div_reg; -		u32 pp_div; - -		pp_ctrl_reg = PP_CONTROL(pipe); -		pp_div_reg  = PP_DIVISOR(pipe); -		pp_div = I915_READ(pp_div_reg); -		pp_div &= PP_REFERENCE_DIVIDER_MASK; - -		/* 0x1F write to PP_DIV_REG sets max cycle delay */ -		I915_WRITE(pp_div_reg, pp_div | 0x1F); -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF); -		msleep(intel_dp->panel_power_cycle_delay); +	with_pps_lock(intel_dp, wakeref) { +		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { +			enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); +			i915_reg_t pp_ctrl_reg, pp_div_reg; +			u32 pp_div; + +			pp_ctrl_reg = PP_CONTROL(pipe); +			pp_div_reg  = PP_DIVISOR(pipe); +			pp_div = I915_READ(pp_div_reg); +			pp_div &= PP_REFERENCE_DIVIDER_MASK; + +			/* 0x1F write to PP_DIV_REG sets max cycle delay */ +			I915_WRITE(pp_div_reg, pp_div | 0x1F); +			I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS); +			msleep(intel_dp->panel_power_cycle_delay); +		}  	} -	pps_unlock(intel_dp); -  	return 0;  } @@ -1041,17 +1050,21 @@ intel_dp_check_edp(struct intel_dp *intel_dp)  	}  } -static uint32_t +static u32  intel_dp_aux_wait_done(struct intel_dp *intel_dp)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); -	uint32_t status; +	u32 status;  	bool done;  #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)  	done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,  				  msecs_to_jiffies_timeout(10)); + +	/* just trace the final value */ +	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); +  	if (!done)  		DRM_ERROR("dp aux hw did not signal timeout!\n");  #undef C @@ -1059,7 +1072,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)  	return status;  } -static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index) +static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -1073,7 +1086,7 @@ static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  	return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);  } -static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) +static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -1092,7 +1105,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  		return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);  } -static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) +static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -1109,7 +1122,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  	return ilk_get_aux_clock_divider(intel_dp, index);  } -static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) +static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  {  	/*  	 * SKL doesn't need us to program the AUX clock divider (Hardware will @@ -1119,16 +1132,16 @@ static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)  	return index ? 0 : 1;  } -static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp, -				     int send_bytes, -				     uint32_t aux_clock_divider) +static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp, +				int send_bytes, +				u32 aux_clock_divider)  {  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	struct drm_i915_private *dev_priv =  			to_i915(intel_dig_port->base.base.dev); -	uint32_t precharge, timeout; +	u32 precharge, timeout; -	if (IS_GEN6(dev_priv)) +	if (IS_GEN(dev_priv, 6))  		precharge = 3;  	else  		precharge = 5; @@ -1149,12 +1162,12 @@ static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp,  	       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);  } -static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp, -				      int send_bytes, -				      uint32_t unused) +static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp, +				int send_bytes, +				u32 unused)  {  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); -	uint32_t ret; +	u32 ret;  	ret = DP_AUX_CH_CTL_SEND_BUSY |  	      DP_AUX_CH_CTL_DONE | @@ -1174,25 +1187,26 @@ static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp,  static int  intel_dp_aux_xfer(struct intel_dp *intel_dp, -		  const uint8_t *send, int send_bytes, -		  uint8_t *recv, int recv_size, +		  const u8 *send, int send_bytes, +		  u8 *recv, int recv_size,  		  u32 aux_send_ctl_flags)  {  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	struct drm_i915_private *dev_priv =  			to_i915(intel_dig_port->base.base.dev);  	i915_reg_t ch_ctl, ch_data[5]; -	uint32_t aux_clock_divider; +	u32 aux_clock_divider; +	intel_wakeref_t wakeref;  	int i, ret, recv_bytes; -	uint32_t status;  	int try, clock = 0; +	u32 status;  	bool vdd;  	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);  	for (i = 0; i < ARRAY_SIZE(ch_data); i++)  		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i); -	pps_lock(intel_dp); +	wakeref = pps_lock(intel_dp);  	/*  	 * We will be called with VDD already enabled for dpcd/edid/oui reads. @@ -1217,6 +1231,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,  			break;  		msleep(1);  	} +	/* just trace the final value */ +	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);  	if (try == 3) {  		static u32 last_status = -1; @@ -1336,7 +1352,7 @@ out:  	if (vdd)  		edp_panel_vdd_off(intel_dp, false); -	pps_unlock(intel_dp); +	pps_unlock(intel_dp, wakeref);  	return ret;  } @@ -1358,7 +1374,7 @@ static ssize_t  intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)  {  	struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux); -	uint8_t txbuf[20], rxbuf[20]; +	u8 txbuf[20], rxbuf[20];  	size_t txsize, rxsize;  	int ret; @@ -1691,7 +1707,7 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)  }  void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, -			   uint8_t *link_bw, uint8_t *rate_select) +			   u8 *link_bw, u8 *rate_select)  {  	/* eDP 1.4 rate select method. */  	if (intel_dp->use_rate_select) { @@ -1808,7 +1824,7 @@ intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,  }  /* Optimize link config in order: max bpp, min clock, min lanes */ -static bool +static int  intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,  				  struct intel_crtc_state *pipe_config,  				  const struct link_config_limits *limits) @@ -1834,17 +1850,17 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,  					pipe_config->pipe_bpp = bpp;  					pipe_config->port_clock = link_clock; -					return true; +					return 0;  				}  			}  		}  	} -	return false; +	return -EINVAL;  }  /* Optimize link config in order: max bpp, min lanes, min clock */ -static bool +static int  intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,  				  struct intel_crtc_state *pipe_config,  				  const struct link_config_limits *limits) @@ -1870,13 +1886,13 @@ intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,  					pipe_config->pipe_bpp = bpp;  					pipe_config->port_clock = link_clock; -					return true; +					return 0;  				}  			}  		}  	} -	return false; +	return -EINVAL;  }  static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc) @@ -1894,19 +1910,20 @@ static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)  	return 0;  } -static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp, -					struct intel_crtc_state *pipe_config, -					struct drm_connector_state *conn_state, -					struct link_config_limits *limits) +static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, +				       struct intel_crtc_state *pipe_config, +				       struct drm_connector_state *conn_state, +				       struct link_config_limits *limits)  {  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);  	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;  	u8 dsc_max_bpc;  	int pipe_bpp; +	int ret;  	if (!intel_dp_supports_dsc(intel_dp, pipe_config)) -		return false; +		return -EINVAL;  	dsc_max_bpc = min_t(u8, DP_DSC_MAX_SUPPORTED_BPC,  			    conn_state->max_requested_bpc); @@ -1914,7 +1931,7 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,  	pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, dsc_max_bpc);  	if (pipe_bpp < DP_DSC_MIN_SUPPORTED_BPC * 3) {  		DRM_DEBUG_KMS("No DSC support for less than 8bpc\n"); -		return false; +		return -EINVAL;  	}  	/* @@ -1948,7 +1965,7 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,  						     adjusted_mode->crtc_hdisplay);  		if (!dsc_max_output_bpp || !dsc_dp_slice_count) {  			DRM_DEBUG_KMS("Compressed BPP/Slice Count not supported\n"); -			return false; +			return -EINVAL;  		}  		pipe_config->dsc_params.compressed_bpp = min_t(u16,  							       dsc_max_output_bpp >> 4, @@ -1965,16 +1982,19 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,  			pipe_config->dsc_params.dsc_split = true;  		} else {  			DRM_DEBUG_KMS("Cannot split stream to use 2 VDSC instances\n"); -			return false; +			return -EINVAL;  		}  	} -	if (intel_dp_compute_dsc_params(intel_dp, pipe_config) < 0) { + +	ret = intel_dp_compute_dsc_params(intel_dp, pipe_config); +	if (ret < 0) {  		DRM_DEBUG_KMS("Cannot compute valid DSC parameters for Input Bpp = %d "  			      "Compressed BPP = %d\n",  			      pipe_config->pipe_bpp,  			      pipe_config->dsc_params.compressed_bpp); -		return false; +		return ret;  	} +  	pipe_config->dsc_params.compression_enable = true;  	DRM_DEBUG_KMS("DP DSC computed with Input Bpp = %d "  		      "Compressed Bpp = %d Slice Count = %d\n", @@ -1982,10 +2002,10 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,  		      pipe_config->dsc_params.compressed_bpp,  		      pipe_config->dsc_params.slice_count); -	return true; +	return 0;  } -static bool +static int  intel_dp_compute_link_config(struct intel_encoder *encoder,  			     struct intel_crtc_state *pipe_config,  			     struct drm_connector_state *conn_state) @@ -1994,7 +2014,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);  	struct link_config_limits limits;  	int common_len; -	bool ret; +	int ret;  	common_len = intel_dp_common_len_rate_limit(intel_dp,  						    intel_dp->max_link_rate); @@ -2051,10 +2071,12 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,  							&limits);  	/* enable compression if the mode doesn't fit available BW */ -	if (!ret) { -		if (!intel_dp_dsc_compute_config(intel_dp, pipe_config, -						 conn_state, &limits)) -			return false; +	DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en); +	if (ret || intel_dp->force_dsc_en) { +		ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, +						  conn_state, &limits); +		if (ret < 0) +			return ret;  	}  	if (pipe_config->dsc_params.compression_enable) { @@ -2079,10 +2101,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,  			      intel_dp_max_data_rate(pipe_config->port_clock,  						     pipe_config->lane_count));  	} -	return true; +	return 0;  } -bool +int  intel_dp_compute_config(struct intel_encoder *encoder,  			struct intel_crtc_state *pipe_config,  			struct drm_connector_state *conn_state) @@ -2098,6 +2120,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,  		to_intel_digital_connector_state(conn_state);  	bool constant_n = drm_dp_has_quirk(&intel_dp->desc,  					   DP_DPCD_QUIRK_CONSTANT_N); +	int ret;  	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)  		pipe_config->has_pch_encoder = true; @@ -2119,14 +2142,12 @@ intel_dp_compute_config(struct intel_encoder *encoder,  				       adjusted_mode);  		if (INTEL_GEN(dev_priv) >= 9) { -			int ret; -  			ret = skl_update_scaler_crtc(pipe_config);  			if (ret)  				return ret;  		} -		if (HAS_GMCH_DISPLAY(dev_priv)) +		if (HAS_GMCH(dev_priv))  			intel_gmch_panel_fitting(intel_crtc, pipe_config,  						 conn_state->scaling_mode);  		else @@ -2135,20 +2156,21 @@ intel_dp_compute_config(struct intel_encoder *encoder,  	}  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) -		return false; +		return -EINVAL; -	if (HAS_GMCH_DISPLAY(dev_priv) && +	if (HAS_GMCH(dev_priv) &&  	    adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) -		return false; +		return -EINVAL;  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) -		return false; +		return -EINVAL;  	pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&  				  intel_dp_supports_fec(intel_dp, pipe_config); -	if (!intel_dp_compute_link_config(encoder, pipe_config, conn_state)) -		return false; +	ret = intel_dp_compute_link_config(encoder, pipe_config, conn_state); +	if (ret < 0) +		return ret;  	if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {  		/* @@ -2196,11 +2218,11 @@ intel_dp_compute_config(struct intel_encoder *encoder,  	intel_psr_compute_config(intel_dp, pipe_config); -	return true; +	return 0;  }  void intel_dp_set_link_params(struct intel_dp *intel_dp, -			      int link_rate, uint8_t lane_count, +			      int link_rate, u8 lane_count,  			      bool link_mst)  {  	intel_dp->link_trained = false; @@ -2462,15 +2484,15 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)   */  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)  { +	intel_wakeref_t wakeref;  	bool vdd;  	if (!intel_dp_is_edp(intel_dp))  		return; -	pps_lock(intel_dp); -	vdd = edp_panel_vdd_on(intel_dp); -	pps_unlock(intel_dp); - +	vdd = false; +	with_pps_lock(intel_dp, wakeref) +		vdd = edp_panel_vdd_on(intel_dp);  	I915_STATE_WARN(!vdd, "eDP port %c VDD already requested on\n",  	     port_name(dp_to_dig_port(intel_dp)->base.port));  } @@ -2509,19 +2531,21 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)  	if ((pp & PANEL_POWER_ON) == 0)  		intel_dp->panel_power_off_time = ktime_get_boottime(); -	intel_display_power_put(dev_priv, -				intel_aux_power_domain(intel_dig_port)); +	intel_display_power_put_unchecked(dev_priv, +					  intel_aux_power_domain(intel_dig_port));  }  static void edp_panel_vdd_work(struct work_struct *__work)  { -	struct intel_dp *intel_dp = container_of(to_delayed_work(__work), -						 struct intel_dp, panel_vdd_work); +	struct intel_dp *intel_dp = +		container_of(to_delayed_work(__work), +			     struct intel_dp, panel_vdd_work); +	intel_wakeref_t wakeref; -	pps_lock(intel_dp); -	if (!intel_dp->want_panel_vdd) -		edp_panel_vdd_off_sync(intel_dp); -	pps_unlock(intel_dp); +	with_pps_lock(intel_dp, wakeref) { +		if (!intel_dp->want_panel_vdd) +			edp_panel_vdd_off_sync(intel_dp); +	}  }  static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp) @@ -2585,7 +2609,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)  	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);  	pp = ironlake_get_pp_control(intel_dp); -	if (IS_GEN5(dev_priv)) { +	if (IS_GEN(dev_priv, 5)) {  		/* ILK workaround: disable reset around power sequence */  		pp &= ~PANEL_POWER_RESET;  		I915_WRITE(pp_ctrl_reg, pp); @@ -2593,7 +2617,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)  	}  	pp |= PANEL_POWER_ON; -	if (!IS_GEN5(dev_priv)) +	if (!IS_GEN(dev_priv, 5))  		pp |= PANEL_POWER_RESET;  	I915_WRITE(pp_ctrl_reg, pp); @@ -2602,7 +2626,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)  	wait_panel_on(intel_dp);  	intel_dp->last_power_on = jiffies; -	if (IS_GEN5(dev_priv)) { +	if (IS_GEN(dev_priv, 5)) {  		pp |= PANEL_POWER_RESET; /* restore panel reset bit */  		I915_WRITE(pp_ctrl_reg, pp);  		POSTING_READ(pp_ctrl_reg); @@ -2611,12 +2635,13 @@ static void edp_panel_on(struct intel_dp *intel_dp)  void intel_edp_panel_on(struct intel_dp *intel_dp)  { +	intel_wakeref_t wakeref; +  	if (!intel_dp_is_edp(intel_dp))  		return; -	pps_lock(intel_dp); -	edp_panel_on(intel_dp); -	pps_unlock(intel_dp); +	with_pps_lock(intel_dp, wakeref) +		edp_panel_on(intel_dp);  } @@ -2655,25 +2680,25 @@ static void edp_panel_off(struct intel_dp *intel_dp)  	intel_dp->panel_power_off_time = ktime_get_boottime();  	/* We got a reference when we enabled the VDD. */ -	intel_display_power_put(dev_priv, intel_aux_power_domain(dig_port)); +	intel_display_power_put_unchecked(dev_priv, intel_aux_power_domain(dig_port));  }  void intel_edp_panel_off(struct intel_dp *intel_dp)  { +	intel_wakeref_t wakeref; +  	if (!intel_dp_is_edp(intel_dp))  		return; -	pps_lock(intel_dp); -	edp_panel_off(intel_dp); -	pps_unlock(intel_dp); +	with_pps_lock(intel_dp, wakeref) +		edp_panel_off(intel_dp);  }  /* Enable backlight in the panel power control. */  static void _intel_edp_backlight_on(struct intel_dp *intel_dp)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); -	u32 pp; -	i915_reg_t pp_ctrl_reg; +	intel_wakeref_t wakeref;  	/*  	 * If we enable the backlight right away following a panel power @@ -2683,17 +2708,16 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)  	 */  	wait_backlight_on(intel_dp); -	pps_lock(intel_dp); +	with_pps_lock(intel_dp, wakeref) { +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp); +		u32 pp; -	pp = ironlake_get_pp_control(intel_dp); -	pp |= EDP_BLC_ENABLE; - -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp); - -	I915_WRITE(pp_ctrl_reg, pp); -	POSTING_READ(pp_ctrl_reg); +		pp = ironlake_get_pp_control(intel_dp); +		pp |= EDP_BLC_ENABLE; -	pps_unlock(intel_dp); +		I915_WRITE(pp_ctrl_reg, pp); +		POSTING_READ(pp_ctrl_reg); +	}  }  /* Enable backlight PWM and backlight PP control. */ @@ -2715,23 +2739,21 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,  static void _intel_edp_backlight_off(struct intel_dp *intel_dp)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); -	u32 pp; -	i915_reg_t pp_ctrl_reg; +	intel_wakeref_t wakeref;  	if (!intel_dp_is_edp(intel_dp))  		return; -	pps_lock(intel_dp); +	with_pps_lock(intel_dp, wakeref) { +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp); +		u32 pp; -	pp = ironlake_get_pp_control(intel_dp); -	pp &= ~EDP_BLC_ENABLE; - -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp); +		pp = ironlake_get_pp_control(intel_dp); +		pp &= ~EDP_BLC_ENABLE; -	I915_WRITE(pp_ctrl_reg, pp); -	POSTING_READ(pp_ctrl_reg); - -	pps_unlock(intel_dp); +		I915_WRITE(pp_ctrl_reg, pp); +		POSTING_READ(pp_ctrl_reg); +	}  	intel_dp->last_backlight_off = jiffies;  	edp_wait_backlight_off(intel_dp); @@ -2759,12 +2781,12 @@ static void intel_edp_backlight_power(struct intel_connector *connector,  				      bool enable)  {  	struct intel_dp *intel_dp = intel_attached_dp(&connector->base); +	intel_wakeref_t wakeref;  	bool is_enabled; -	pps_lock(intel_dp); -	is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE; -	pps_unlock(intel_dp); - +	is_enabled = false; +	with_pps_lock(intel_dp, wakeref) +		is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;  	if (is_enabled == enable)  		return; @@ -2831,7 +2853,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp,  	 * 1. Wait for the start of vertical blank on the enabled pipe going to FDI  	 * 2. Program DP PLL enable  	 */ -	if (IS_GEN5(dev_priv)) +	if (IS_GEN(dev_priv, 5))  		intel_wait_for_vblank_if_active(dev_priv, !crtc->pipe);  	intel_dp->DP |= DP_PLL_ENABLE; @@ -2981,16 +3003,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); +	intel_wakeref_t wakeref;  	bool ret; -	if (!intel_display_power_get_if_enabled(dev_priv, -						encoder->power_domain)) +	wakeref = intel_display_power_get_if_enabled(dev_priv, +						     encoder->power_domain); +	if (!wakeref)  		return false;  	ret = intel_dp_port_enabled(dev_priv, intel_dp->output_reg,  				    encoder->port, pipe); -	intel_display_power_put(dev_priv, encoder->power_domain); +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);  	return ret;  } @@ -3158,20 +3182,20 @@ static void chv_post_disable_dp(struct intel_encoder *encoder,  static void  _intel_dp_set_link_train(struct intel_dp *intel_dp, -			 uint32_t *DP, -			 uint8_t dp_train_pat) +			 u32 *DP, +			 u8 dp_train_pat)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	enum port port = intel_dig_port->base.port; -	uint8_t train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd); +	u8 train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd);  	if (dp_train_pat & train_pat_mask)  		DRM_DEBUG_KMS("Using DP training pattern TPS%d\n",  			      dp_train_pat & train_pat_mask);  	if (HAS_DDI(dev_priv)) { -		uint32_t temp = I915_READ(DP_TP_CTL(port)); +		u32 temp = I915_READ(DP_TP_CTL(port));  		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)  			temp |= DP_TP_CTL_SCRAMBLE_DISABLE; @@ -3270,24 +3294,23 @@ static void intel_enable_dp(struct intel_encoder *encoder,  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);  	struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); -	uint32_t dp_reg = I915_READ(intel_dp->output_reg); +	u32 dp_reg = I915_READ(intel_dp->output_reg);  	enum pipe pipe = crtc->pipe; +	intel_wakeref_t wakeref;  	if (WARN_ON(dp_reg & DP_PORT_EN))  		return; -	pps_lock(intel_dp); +	with_pps_lock(intel_dp, wakeref) { +		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) +			vlv_init_panel_power_sequencer(encoder, pipe_config); -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) -		vlv_init_panel_power_sequencer(encoder, pipe_config); +		intel_dp_enable_port(intel_dp, pipe_config); -	intel_dp_enable_port(intel_dp, pipe_config); - -	edp_panel_vdd_on(intel_dp); -	edp_panel_on(intel_dp); -	edp_panel_vdd_off(intel_dp, true); - -	pps_unlock(intel_dp); +		edp_panel_vdd_on(intel_dp); +		edp_panel_on(intel_dp); +		edp_panel_vdd_off(intel_dp, true); +	}  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {  		unsigned int lane_mask = 0x0; @@ -3490,14 +3513,14 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder,   * link status information   */  bool -intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) +intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE])  {  	return drm_dp_dpcd_read(&intel_dp->aux, DP_LANE0_1_STATUS, link_status,  				DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;  }  /* These are source-specific values. */ -uint8_t +u8  intel_dp_voltage_max(struct intel_dp *intel_dp)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -3516,8 +3539,8 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)  		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;  } -uint8_t -intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) +u8 +intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing)  {  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; @@ -3562,12 +3585,12 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)  	}  } -static uint32_t vlv_signal_levels(struct intel_dp *intel_dp) +static u32 vlv_signal_levels(struct intel_dp *intel_dp)  {  	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;  	unsigned long demph_reg_value, preemph_reg_value,  		uniqtranscale_reg_value; -	uint8_t train_set = intel_dp->train_set[0]; +	u8 train_set = intel_dp->train_set[0];  	switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {  	case DP_TRAIN_PRE_EMPH_LEVEL_0: @@ -3648,12 +3671,12 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)  	return 0;  } -static uint32_t chv_signal_levels(struct intel_dp *intel_dp) +static u32 chv_signal_levels(struct intel_dp *intel_dp)  {  	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;  	u32 deemph_reg_value, margin_reg_value;  	bool uniq_trans_scale = false; -	uint8_t train_set = intel_dp->train_set[0]; +	u8 train_set = intel_dp->train_set[0];  	switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {  	case DP_TRAIN_PRE_EMPH_LEVEL_0: @@ -3731,10 +3754,10 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)  	return 0;  } -static uint32_t -g4x_signal_levels(uint8_t train_set) +static u32 +g4x_signal_levels(u8 train_set)  { -	uint32_t	signal_levels = 0; +	u32 signal_levels = 0;  	switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {  	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: @@ -3770,8 +3793,8 @@ g4x_signal_levels(uint8_t train_set)  }  /* SNB CPU eDP voltage swing and pre-emphasis control */ -static uint32_t -snb_cpu_edp_signal_levels(uint8_t train_set) +static u32 +snb_cpu_edp_signal_levels(u8 train_set)  {  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3798,8 +3821,8 @@ snb_cpu_edp_signal_levels(uint8_t train_set)  }  /* IVB CPU eDP voltage swing and pre-emphasis control */ -static uint32_t -ivb_cpu_edp_signal_levels(uint8_t train_set) +static u32 +ivb_cpu_edp_signal_levels(u8 train_set)  {  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3834,8 +3857,8 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	enum port port = intel_dig_port->base.port; -	uint32_t signal_levels, mask = 0; -	uint8_t train_set = intel_dp->train_set[0]; +	u32 signal_levels, mask = 0; +	u8 train_set = intel_dp->train_set[0];  	if (IS_GEN9_LP(dev_priv) || INTEL_GEN(dev_priv) >= 10) {  		signal_levels = bxt_signal_levels(intel_dp); @@ -3849,7 +3872,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)  	} else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {  		signal_levels = ivb_cpu_edp_signal_levels(train_set);  		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; -	} else if (IS_GEN6(dev_priv) && port == PORT_A) { +	} else if (IS_GEN(dev_priv, 6) && port == PORT_A) {  		signal_levels = snb_cpu_edp_signal_levels(train_set);  		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;  	} else { @@ -3874,7 +3897,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)  void  intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, -				       uint8_t dp_train_pat) +				       u8 dp_train_pat)  {  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	struct drm_i915_private *dev_priv = @@ -3891,7 +3914,7 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	enum port port = intel_dig_port->base.port; -	uint32_t val; +	u32 val;  	if (!HAS_DDI(dev_priv))  		return; @@ -3926,7 +3949,7 @@ intel_dp_link_down(struct intel_encoder *encoder,  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);  	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);  	enum port port = encoder->port; -	uint32_t DP = intel_dp->DP; +	u32 DP = intel_dp->DP;  	if (WARN_ON(HAS_DDI(dev_priv)))  		return; @@ -3985,12 +4008,49 @@ intel_dp_link_down(struct intel_encoder *encoder,  	intel_dp->DP = DP;  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { -		pps_lock(intel_dp); -		intel_dp->active_pipe = INVALID_PIPE; -		pps_unlock(intel_dp); +		intel_wakeref_t wakeref; + +		with_pps_lock(intel_dp, wakeref) +			intel_dp->active_pipe = INVALID_PIPE;  	}  } +static void +intel_dp_extended_receiver_capabilities(struct intel_dp *intel_dp) +{ +	u8 dpcd_ext[6]; + +	/* +	 * Prior to DP1.3 the bit represented by +	 * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. +	 * if it is set DP_DPCD_REV at 0000h could be at a value less than +	 * the true capability of the panel. The only way to check is to +	 * then compare 0000h and 2200h. +	 */ +	if (!(intel_dp->dpcd[DP_TRAINING_AUX_RD_INTERVAL] & +	      DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) +		return; + +	if (drm_dp_dpcd_read(&intel_dp->aux, DP_DP13_DPCD_REV, +			     &dpcd_ext, sizeof(dpcd_ext)) != sizeof(dpcd_ext)) { +		DRM_ERROR("DPCD failed read at extended capabilities\n"); +		return; +	} + +	if (intel_dp->dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { +		DRM_DEBUG_KMS("DPCD extended DPCD rev less than base DPCD rev\n"); +		return; +	} + +	if (!memcmp(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext))) +		return; + +	DRM_DEBUG_KMS("Base DPCD: %*ph\n", +		      (int)sizeof(intel_dp->dpcd), intel_dp->dpcd); + +	memcpy(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext)); +} +  bool  intel_dp_read_dpcd(struct intel_dp *intel_dp)  { @@ -3998,6 +4058,8 @@ intel_dp_read_dpcd(struct intel_dp *intel_dp)  			     sizeof(intel_dp->dpcd)) < 0)  		return false; /* aux transfer failed */ +	intel_dp_extended_receiver_capabilities(intel_dp); +  	DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd);  	return intel_dp->dpcd[DP_DPCD_REV] != 0; @@ -4228,7 +4290,7 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)  		DP_DPRX_ESI_LEN;  } -u16 intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count, +u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count,  				int mode_clock, int mode_hdisplay)  {  	u16 bits_per_pixel, max_bpp_small_joiner_ram; @@ -4295,7 +4357,7 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,  		return 0;  	}  	/* Also take into account max slice width */ -	min_slice_count = min_t(uint8_t, min_slice_count, +	min_slice_count = min_t(u8, min_slice_count,  				DIV_ROUND_UP(mode_hdisplay,  					     max_slice_width)); @@ -4313,11 +4375,11 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,  	return 0;  } -static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp) +static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp)  {  	int status = 0;  	int test_link_rate; -	uint8_t test_lane_count, test_link_bw; +	u8 test_lane_count, test_link_bw;  	/* (DP CTS 1.2)  	 * 4.3.1.11  	 */ @@ -4350,10 +4412,10 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)  	return DP_TEST_ACK;  } -static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp) +static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)  { -	uint8_t test_pattern; -	uint8_t test_misc; +	u8 test_pattern; +	u8 test_misc;  	__be16 h_width, v_height;  	int status = 0; @@ -4411,9 +4473,9 @@ static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)  	return DP_TEST_ACK;  } -static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp) +static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp)  { -	uint8_t test_result = DP_TEST_ACK; +	u8 test_result = DP_TEST_ACK;  	struct intel_connector *intel_connector = intel_dp->attached_connector;  	struct drm_connector *connector = &intel_connector->base; @@ -4455,16 +4517,16 @@ static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp)  	return test_result;  } -static uint8_t intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp) +static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)  { -	uint8_t test_result = DP_TEST_NAK; +	u8 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 request = 0; +	u8 response = DP_TEST_NAK; +	u8 request = 0;  	int status;  	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_REQUEST, &request); @@ -4552,12 +4614,10 @@ go_again:  			return ret;  		} else { -			struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  			DRM_DEBUG_KMS("failed to get ESI - device may have failed\n");  			intel_dp->is_mst = false; -			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); -			/* send a hotplug event */ -			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev); +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, +							intel_dp->is_mst);  		}  	}  	return -EINVAL; @@ -4790,8 +4850,8 @@ static enum drm_connector_status  intel_dp_detect_dpcd(struct intel_dp *intel_dp)  {  	struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp); -	uint8_t *dpcd = intel_dp->dpcd; -	uint8_t type; +	u8 *dpcd = intel_dp->dpcd; +	u8 type;  	if (lspcon->active)  		lspcon_resume(lspcon); @@ -5028,28 +5088,38 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv,  	return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);  } +static const char *tc_type_name(enum tc_port_type type) +{ +	static const char * const names[] = { +		[TC_PORT_UNKNOWN] = "unknown", +		[TC_PORT_LEGACY] = "legacy", +		[TC_PORT_TYPEC] = "typec", +		[TC_PORT_TBT] = "tbt", +	}; + +	if (WARN_ON(type >= ARRAY_SIZE(names))) +		type = TC_PORT_UNKNOWN; + +	return names[type]; +} +  static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,  				    struct intel_digital_port *intel_dig_port,  				    bool is_legacy, bool is_typec, bool is_tbt)  {  	enum port port = intel_dig_port->base.port;  	enum tc_port_type old_type = intel_dig_port->tc_type; -	const char *type_str;  	WARN_ON(is_legacy + is_typec + is_tbt != 1); -	if (is_legacy) { +	if (is_legacy)  		intel_dig_port->tc_type = TC_PORT_LEGACY; -		type_str = "legacy"; -	} else if (is_typec) { +	else if (is_typec)  		intel_dig_port->tc_type = TC_PORT_TYPEC; -		type_str = "typec"; -	} else if (is_tbt) { +	else if (is_tbt)  		intel_dig_port->tc_type = TC_PORT_TBT; -		type_str = "tbt"; -	} else { +	else  		return; -	}  	/* Types are not supposed to be changed at runtime. */  	WARN_ON(old_type != TC_PORT_UNKNOWN && @@ -5057,12 +5127,9 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,  	if (old_type != intel_dig_port->tc_type)  		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port), -			      type_str); +			      tc_type_name(intel_dig_port->tc_type));  } -static void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv, -				  struct intel_digital_port *dig_port); -  /*   * This function implements the first part of the Connect Flow described by our   * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading @@ -5097,6 +5164,7 @@ static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,  	val = I915_READ(PORT_TX_DFLEXDPPMS);  	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {  		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port); +		WARN_ON(dig_port->tc_legacy_port);  		return false;  	} @@ -5128,8 +5196,8 @@ static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,   * See the comment at the connect function. This implements the Disconnect   * Flow.   */ -static void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv, -				  struct intel_digital_port *dig_port) +void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv, +			   struct intel_digital_port *dig_port)  {  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port); @@ -5149,6 +5217,10 @@ static void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,  		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);  	} +	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n", +		      port_name(dig_port->base.port), +		      tc_type_name(dig_port->tc_type)); +  	dig_port->tc_type = TC_PORT_UNKNOWN;  } @@ -5170,7 +5242,14 @@ static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,  	bool is_legacy, is_typec, is_tbt;  	u32 dpsp; -	is_legacy = I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port); +	/* +	 * WARN if we got a legacy port HPD, but VBT didn't mark the port as +	 * legacy. Treat the port as legacy from now on. +	 */ +	if (WARN_ON(!intel_dig_port->tc_legacy_port && +		    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))) +		intel_dig_port->tc_legacy_port = true; +	is_legacy = intel_dig_port->tc_legacy_port;  	/*  	 * The spec says we shouldn't be using the ISR bits for detecting @@ -5182,6 +5261,7 @@ static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,  	if (!is_legacy && !is_typec && !is_tbt) {  		icl_tc_phy_disconnect(dev_priv, intel_dig_port); +  		return false;  	} @@ -5224,7 +5304,7 @@ bool intel_digital_port_connected(struct intel_encoder *encoder)  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); -	if (HAS_GMCH_DISPLAY(dev_priv)) { +	if (HAS_GMCH(dev_priv)) {  		if (IS_GM45(dev_priv))  			return gm45_digital_port_connected(encoder);  		else @@ -5233,17 +5313,17 @@ bool intel_digital_port_connected(struct intel_encoder *encoder)  	if (INTEL_GEN(dev_priv) >= 11)  		return icl_digital_port_connected(encoder); -	else if (IS_GEN10(dev_priv) || IS_GEN9_BC(dev_priv)) +	else if (IS_GEN(dev_priv, 10) || IS_GEN9_BC(dev_priv))  		return spt_digital_port_connected(encoder);  	else if (IS_GEN9_LP(dev_priv))  		return bxt_digital_port_connected(encoder); -	else if (IS_GEN8(dev_priv)) +	else if (IS_GEN(dev_priv, 8))  		return bdw_digital_port_connected(encoder); -	else if (IS_GEN7(dev_priv)) +	else if (IS_GEN(dev_priv, 7))  		return ivb_digital_port_connected(encoder); -	else if (IS_GEN6(dev_priv)) +	else if (IS_GEN(dev_priv, 6))  		return snb_digital_port_connected(encoder); -	else if (IS_GEN5(dev_priv)) +	else if (IS_GEN(dev_priv, 5))  		return ilk_digital_port_connected(encoder);  	MISSING_CASE(INTEL_GEN(dev_priv)); @@ -5305,12 +5385,13 @@ intel_dp_detect(struct drm_connector *connector,  	enum drm_connector_status status;  	enum intel_display_power_domain aux_domain =  		intel_aux_power_domain(dig_port); +	intel_wakeref_t wakeref;  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",  		      connector->base.id, connector->name);  	WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); -	intel_display_power_get(dev_priv, aux_domain); +	wakeref = intel_display_power_get(dev_priv, aux_domain);  	/* Can't disconnect eDP */  	if (intel_dp_is_edp(intel_dp)) @@ -5376,7 +5457,7 @@ intel_dp_detect(struct drm_connector *connector,  		ret = intel_dp_retrain_link(encoder, ctx);  		if (ret) { -			intel_display_power_put(dev_priv, aux_domain); +			intel_display_power_put(dev_priv, aux_domain, wakeref);  			return ret;  		}  	} @@ -5400,7 +5481,7 @@ out:  	if (status != connector_status_connected && !intel_dp->is_mst)  		intel_dp_unset_edid(intel_dp); -	intel_display_power_put(dev_priv, aux_domain); +	intel_display_power_put(dev_priv, aux_domain, wakeref);  	return status;  } @@ -5413,6 +5494,7 @@ intel_dp_force(struct drm_connector *connector)  	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);  	enum intel_display_power_domain aux_domain =  		intel_aux_power_domain(dig_port); +	intel_wakeref_t wakeref;  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",  		      connector->base.id, connector->name); @@ -5421,11 +5503,11 @@ intel_dp_force(struct drm_connector *connector)  	if (connector->status != connector_status_connected)  		return; -	intel_display_power_get(dev_priv, aux_domain); +	wakeref = intel_display_power_get(dev_priv, aux_domain);  	intel_dp_set_edid(intel_dp); -	intel_display_power_put(dev_priv, aux_domain); +	intel_display_power_put(dev_priv, aux_domain, wakeref);  }  static int intel_dp_get_modes(struct drm_connector *connector) @@ -5490,21 +5572,22 @@ intel_dp_connector_unregister(struct drm_connector *connector)  	intel_connector_unregister(connector);  } -void intel_dp_encoder_destroy(struct drm_encoder *encoder) +void intel_dp_encoder_flush_work(struct drm_encoder *encoder)  {  	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);  	struct intel_dp *intel_dp = &intel_dig_port->dp;  	intel_dp_mst_encoder_cleanup(intel_dig_port);  	if (intel_dp_is_edp(intel_dp)) { +		intel_wakeref_t wakeref; +  		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);  		/*  		 * vdd might still be enabled do to the delayed vdd off.  		 * Make sure vdd is actually turned off here.  		 */ -		pps_lock(intel_dp); -		edp_panel_vdd_off_sync(intel_dp); -		pps_unlock(intel_dp); +		with_pps_lock(intel_dp, wakeref) +			edp_panel_vdd_off_sync(intel_dp);  		if (intel_dp->edp_notifier.notifier_call) {  			unregister_reboot_notifier(&intel_dp->edp_notifier); @@ -5513,14 +5596,20 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)  	}  	intel_dp_aux_fini(intel_dp); +} + +static void intel_dp_encoder_destroy(struct drm_encoder *encoder) +{ +	intel_dp_encoder_flush_work(encoder);  	drm_encoder_cleanup(encoder); -	kfree(intel_dig_port); +	kfree(enc_to_dig_port(encoder));  }  void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)  {  	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); +	intel_wakeref_t wakeref;  	if (!intel_dp_is_edp(intel_dp))  		return; @@ -5530,9 +5619,8 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)  	 * Make sure vdd is actually turned off here.  	 */  	cancel_delayed_work_sync(&intel_dp->panel_vdd_work); -	pps_lock(intel_dp); -	edp_panel_vdd_off_sync(intel_dp); -	pps_unlock(intel_dp); +	with_pps_lock(intel_dp, wakeref) +		edp_panel_vdd_off_sync(intel_dp);  }  static @@ -5545,7 +5633,7 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,  		.address = DP_AUX_HDCP_AKSV,  		.size = DRM_HDCP_KSV_LEN,  	}; -	uint8_t txbuf[HEADER_SIZE + DRM_HDCP_KSV_LEN] = {}, rxbuf[2], reply = 0; +	u8 txbuf[HEADER_SIZE + DRM_HDCP_KSV_LEN] = {}, rxbuf[2], reply = 0;  	ssize_t dpcd_ret;  	int ret; @@ -5578,7 +5666,12 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,  	}  	reply = (rxbuf[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK; -	return reply == DP_AUX_NATIVE_REPLY_ACK ? 0 : -EIO; +	if (reply != DP_AUX_NATIVE_REPLY_ACK) { +		DRM_DEBUG_KMS("Aksv write: no DP_AUX_NATIVE_REPLY_ACK %x\n", +			      reply); +		return -EIO; +	} +	return 0;  }  static int intel_dp_hdcp_read_bksv(struct intel_digital_port *intel_dig_port, @@ -5808,6 +5901,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)  	struct drm_i915_private *dev_priv = to_i915(encoder->dev);  	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);  	struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp); +	intel_wakeref_t wakeref;  	if (!HAS_DDI(dev_priv))  		intel_dp->DP = I915_READ(intel_dp->output_reg); @@ -5817,18 +5911,19 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)  	intel_dp->reset_link_params = true; -	pps_lock(intel_dp); - -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) -		intel_dp->active_pipe = vlv_active_pipe(intel_dp); +	with_pps_lock(intel_dp, wakeref) { +		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) +			intel_dp->active_pipe = vlv_active_pipe(intel_dp); -	if (intel_dp_is_edp(intel_dp)) { -		/* Reinit the power sequencer, in case BIOS did something with it. */ -		intel_dp_pps_init(intel_dp); -		intel_edp_panel_vdd_sanitize(intel_dp); +		if (intel_dp_is_edp(intel_dp)) { +			/* +			 * Reinit the power sequencer, in case BIOS did +			 * something nasty with it. +			 */ +			intel_dp_pps_init(intel_dp); +			intel_edp_panel_vdd_sanitize(intel_dp); +		}  	} - -	pps_unlock(intel_dp);  }  static const struct drm_connector_funcs intel_dp_connector_funcs = { @@ -5861,6 +5956,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)  	struct intel_dp *intel_dp = &intel_dig_port->dp;  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);  	enum irqreturn ret = IRQ_NONE; +	intel_wakeref_t wakeref;  	if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {  		/* @@ -5883,8 +5979,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)  		return IRQ_NONE;  	} -	intel_display_power_get(dev_priv, -				intel_aux_power_domain(intel_dig_port)); +	wakeref = intel_display_power_get(dev_priv, +					  intel_aux_power_domain(intel_dig_port));  	if (intel_dp->is_mst) {  		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) { @@ -5914,7 +6010,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)  put_power:  	intel_display_power_put(dev_priv, -				intel_aux_power_domain(intel_dig_port)); +				intel_aux_power_domain(intel_dig_port), +				wakeref);  	return ret;  } @@ -5945,7 +6042,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect  		intel_attach_force_audio_property(connector);  	intel_attach_broadcast_rgb_property(connector); -	if (HAS_GMCH_DISPLAY(dev_priv)) +	if (HAS_GMCH(dev_priv))  		drm_connector_attach_max_bpc_property(connector, 6, 10);  	else if (INTEL_GEN(dev_priv) >= 5)  		drm_connector_attach_max_bpc_property(connector, 6, 12); @@ -5954,7 +6051,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect  		u32 allowed_scalers;  		allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN); -		if (!HAS_GMCH_DISPLAY(dev_priv)) +		if (!HAS_GMCH(dev_priv))  			allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER);  		drm_connector_attach_scaling_mode_property(connector, allowed_scalers); @@ -6361,8 +6458,8 @@ void intel_edp_drrs_enable(struct intel_dp *intel_dp,  	}  	mutex_lock(&dev_priv->drrs.mutex); -	if (WARN_ON(dev_priv->drrs.dp)) { -		DRM_ERROR("DRRS already enabled\n"); +	if (dev_priv->drrs.dp) { +		DRM_DEBUG_KMS("DRRS already enabled\n");  		goto unlock;  	} @@ -6622,8 +6719,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,  	struct drm_display_mode *downclock_mode = NULL;  	bool has_dpcd;  	struct drm_display_mode *scan; -	struct edid *edid;  	enum pipe pipe = INVALID_PIPE; +	intel_wakeref_t wakeref; +	struct edid *edid;  	if (!intel_dp_is_edp(intel_dp))  		return true; @@ -6643,13 +6741,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,  		return false;  	} -	pps_lock(intel_dp); - -	intel_dp_init_panel_power_timestamps(intel_dp); -	intel_dp_pps_init(intel_dp); -	intel_edp_panel_vdd_sanitize(intel_dp); - -	pps_unlock(intel_dp); +	with_pps_lock(intel_dp, wakeref) { +		intel_dp_init_panel_power_timestamps(intel_dp); +		intel_dp_pps_init(intel_dp); +		intel_edp_panel_vdd_sanitize(intel_dp); +	}  	/* Cache DPCD and EDID for edp. */  	has_dpcd = intel_edp_init_dpcd(intel_dp); @@ -6734,9 +6830,8 @@ out_vdd_off:  	 * vdd might still be enabled do to the delayed vdd off.  	 * Make sure vdd is actually turned off here.  	 */ -	pps_lock(intel_dp); -	edp_panel_vdd_off_sync(intel_dp); -	pps_unlock(intel_dp); +	with_pps_lock(intel_dp, wakeref) +		edp_panel_vdd_off_sync(intel_dp);  	return false;  } @@ -6828,7 +6923,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,  	drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);  	drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); -	if (!HAS_GMCH_DISPLAY(dev_priv)) +	if (!HAS_GMCH(dev_priv))  		connector->interlace_allowed = true;  	connector->doublescan_allowed = 0; @@ -6910,6 +7005,7 @@ bool intel_dp_init(struct drm_i915_private *dev_priv,  	intel_encoder->compute_config = intel_dp_compute_config;  	intel_encoder->get_hw_state = intel_dp_get_hw_state;  	intel_encoder->get_config = intel_dp_get_config; +	intel_encoder->update_pipe = intel_panel_update_backlight;  	intel_encoder->suspend = intel_dp_encoder_suspend;  	if (IS_CHERRYVIEW(dev_priv)) {  		intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; @@ -7004,7 +7100,10 @@ void intel_dp_mst_resume(struct drm_i915_private *dev_priv)  			continue;  		ret = drm_dp_mst_topology_mgr_resume(&intel_dp->mst_mgr); -		if (ret) -			intel_dp_check_mst_status(intel_dp); +		if (ret) { +			intel_dp->is_mst = false; +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, +							false); +		}  	}  } | 
