diff options
| author | Dave Airlie <airlied@redhat.com> | 2013-01-17 20:34:08 +1000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2013-01-17 20:34:08 +1000 | 
| commit | b5cc6c0387b2f8d269c1df1e68c97c958dd22fed (patch) | |
| tree | 697f2335b3a10f55e0ea226dcd044ee4ff3f0f7f /drivers/gpu/drm/i915/intel_dp.c | |
| parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) | |
| parent | c0c36b941b6f0be6ac74f340040cbb29d6a0b06c (diff) | |
| download | olio-linux-3.10-b5cc6c0387b2f8d269c1df1e68c97c958dd22fed.tar.xz olio-linux-3.10-b5cc6c0387b2f8d269c1df1e68c97c958dd22fed.zip  | |
Merge tag 'drm-intel-next-2012-12-21' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
Daniel writes:
- seqno wrap fixes and debug infrastructure from Mika Kuoppala and Chris
  Wilson
- some leftover kill-agp on gen6+ patches from Ben
- hotplug improvements from Damien
- clear fb when allocated from stolen, avoids dirt on the fbcon (Chris)
- Stolen mem support from Chris Wilson, one of the many steps to get to
  real fastboot support.
- Some DDI code cleanups from Paulo.
- Some refactorings around lvds and dp code.
- some random little bits&pieces
* tag 'drm-intel-next-2012-12-21' of git://people.freedesktop.org/~danvet/drm-intel: (93 commits)
  drm/i915: Return the real error code from intel_set_mode()
  drm/i915: Make GSM void
  drm/i915: Move GSM mapping into dev_priv
  drm/i915: Move even more gtt code to i915_gem_gtt
  drm/i915: Make next_seqno debugs entry to use i915_gem_set_seqno
  drm/i915: Introduce i915_gem_set_seqno()
  drm/i915: Always clear semaphore mboxes on seqno wrap
  drm/i915: Initialize hardware semaphore state on ring init
  drm/i915: Introduce ring set_seqno
  drm/i915: Missed conversion to gtt_pte_t
  drm/i915: Bug on unsupported swizzled platforms
  drm/i915: BUG() if fences are used on unsupported platform
  drm/i915: fixup overlay stolen memory leak
  drm/i915: clean up PIPECONF bpc #defines
  drm/i915: add intel_dp_set_signal_levels
  drm/i915: remove leftover display.update_wm assignment
  drm/i915: check for the PCH when setting pch_transcoder
  drm/i915: Clear the stolen fb before enabling
  drm/i915: Access to snooped system memory through the GTT is incoherent
  drm/i915: Remove stale comment about intel_dp_detect()
  ...
Conflicts:
	drivers/gpu/drm/i915/intel_display.c
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 293 | 
1 files changed, 164 insertions, 129 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b63d55318a..5f12eb2d0fb 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -148,15 +148,6 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp)  	return max_link_bw;  } -static int -intel_dp_link_clock(uint8_t link_bw) -{ -	if (link_bw == DP_LINK_BW_2_7) -		return 270000; -	else -		return 162000; -} -  /*   * The units on the numbers in the next two are... bizarre.  Examples will   * make it clearer; this one parallels an example in the eDP spec. @@ -191,7 +182,8 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp,  			  struct drm_display_mode *mode,  			  bool adjust_mode)  { -	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); +	int max_link_clock = +		drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp));  	int max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);  	int max_rate, mode_rate; @@ -330,6 +322,48 @@ intel_dp_check_edp(struct intel_dp *intel_dp)  	}  } +static uint32_t +intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) +{ +	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; +	uint32_t ch_ctl = intel_dp->output_reg + 0x10; +	uint32_t status; +	bool done; + +	if (IS_HASWELL(dev)) { +		switch (intel_dig_port->port) { +		case PORT_A: +			ch_ctl = DPA_AUX_CH_CTL; +			break; +		case PORT_B: +			ch_ctl = PCH_DPB_AUX_CH_CTL; +			break; +		case PORT_C: +			ch_ctl = PCH_DPC_AUX_CH_CTL; +			break; +		case PORT_D: +			ch_ctl = PCH_DPD_AUX_CH_CTL; +			break; +		default: +			BUG(); +		} +	} + +#define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) +	if (has_aux_irq) +		done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10); +	else +		done = wait_for_atomic(C, 10) == 0; +	if (!done) +		DRM_ERROR("dp aux hw did not signal timeout (has irq: %i)!\n", +			  has_aux_irq); +#undef C + +	return status; +} +  static int  intel_dp_aux_ch(struct intel_dp *intel_dp,  		uint8_t *send, int send_bytes, @@ -341,11 +375,17 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	struct drm_i915_private *dev_priv = dev->dev_private;  	uint32_t ch_ctl = output_reg + 0x10;  	uint32_t ch_data = ch_ctl + 4; -	int i; -	int recv_bytes; +	int i, ret, recv_bytes;  	uint32_t status;  	uint32_t aux_clock_divider;  	int try, precharge; +	bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev); + +	/* dp aux is extremely sensitive to irq latency, hence request the +	 * lowest possible wakeup latency and so prevent the cpu from going into +	 * deep sleep states. +	 */ +	pm_qos_update_request(&dev_priv->pm_qos, 0);  	if (IS_HASWELL(dev)) {  		switch (intel_dig_port->port) { @@ -379,7 +419,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	 * clock divider.  	 */  	if (is_cpu_edp(intel_dp)) { -		if (IS_HASWELL(dev)) +		if (HAS_DDI(dev))  			aux_clock_divider = intel_ddi_get_cdclk_freq(dev_priv) >> 1;  		else if (IS_VALLEYVIEW(dev))  			aux_clock_divider = 100; @@ -399,7 +439,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	/* Try to wait for any previous AUX channel activity */  	for (try = 0; try < 3; try++) { -		status = I915_READ(ch_ctl); +		status = I915_READ_NOTRACE(ch_ctl);  		if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)  			break;  		msleep(1); @@ -408,7 +448,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	if (try == 3) {  		WARN(1, "dp_aux_ch not started status 0x%08x\n",  		     I915_READ(ch_ctl)); -		return -EBUSY; +		ret = -EBUSY; +		goto out;  	}  	/* Must try at least 3 times according to DP spec */ @@ -421,6 +462,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  		/* Send the command and wait for it to complete */  		I915_WRITE(ch_ctl,  			   DP_AUX_CH_CTL_SEND_BUSY | +			   (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |  			   DP_AUX_CH_CTL_TIME_OUT_400us |  			   (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |  			   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | @@ -428,12 +470,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  			   DP_AUX_CH_CTL_DONE |  			   DP_AUX_CH_CTL_TIME_OUT_ERROR |  			   DP_AUX_CH_CTL_RECEIVE_ERROR); -		for (;;) { -			status = I915_READ(ch_ctl); -			if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) -				break; -			udelay(100); -		} + +		status = intel_dp_aux_wait_done(intel_dp, has_aux_irq);  		/* Clear done status and any errors */  		I915_WRITE(ch_ctl, @@ -451,7 +489,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	if ((status & DP_AUX_CH_CTL_DONE) == 0) {  		DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); -		return -EBUSY; +		ret = -EBUSY; +		goto out;  	}  	/* Check for timeout or receive error. @@ -459,14 +498,16 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	 */  	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {  		DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); -		return -EIO; +		ret = -EIO; +		goto out;  	}  	/* Timeouts occur when the device isn't connected, so they're  	 * "normal" -- don't fill the kernel log with these */  	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {  		DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status); -		return -ETIMEDOUT; +		ret = -ETIMEDOUT; +		goto out;  	}  	/* Unload any bytes sent back from the other side */ @@ -479,7 +520,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  		unpack_aux(I915_READ(ch_data + i),  			   recv + i, recv_bytes - i); -	return recv_bytes; +	ret = recv_bytes; +out: +	pm_qos_update_request(&dev_priv->pm_qos, PM_QOS_DEFAULT_VALUE); + +	return ret;  }  /* Write data to the aux channel in native mode */ @@ -722,12 +767,15 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,  	for (clock = 0; clock <= max_clock; clock++) {  		for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { -			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); +			int link_bw_clock = +				drm_dp_bw_code_to_link_rate(bws[clock]); +			int link_avail = intel_dp_max_data_rate(link_bw_clock, +								lane_count);  			if (mode_rate <= link_avail) {  				intel_dp->link_bw = bws[clock];  				intel_dp->lane_count = lane_count; -				adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); +				adjusted_mode->clock = link_bw_clock;  				DRM_DEBUG_KMS("DP link bw %02x lane "  						"count %d clock %d bpp %d\n",  				       intel_dp->link_bw, intel_dp->lane_count, @@ -742,39 +790,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,  	return false;  } -struct intel_dp_m_n { -	uint32_t	tu; -	uint32_t	gmch_m; -	uint32_t	gmch_n; -	uint32_t	link_m; -	uint32_t	link_n; -}; - -static void -intel_reduce_ratio(uint32_t *num, uint32_t *den) -{ -	while (*num > 0xffffff || *den > 0xffffff) { -		*num >>= 1; -		*den >>= 1; -	} -} - -static void -intel_dp_compute_m_n(int bpp, -		     int nlanes, -		     int pixel_clock, -		     int link_clock, -		     struct intel_dp_m_n *m_n) -{ -	m_n->tu = 64; -	m_n->gmch_m = (pixel_clock * bpp) >> 3; -	m_n->gmch_n = link_clock * nlanes; -	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); -	m_n->link_m = pixel_clock; -	m_n->link_n = link_clock; -	intel_reduce_ratio(&m_n->link_m, &m_n->link_n); -} -  void  intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,  		 struct drm_display_mode *adjusted_mode) @@ -785,7 +800,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	int lane_count = 4; -	struct intel_dp_m_n m_n; +	struct intel_link_m_n m_n;  	int pipe = intel_crtc->pipe;  	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; @@ -808,8 +823,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,  	 * the number of bytes_per_pixel post-LUT, which we always  	 * set up for 8-bits of R/G/B, or 3 bytes total.  	 */ -	intel_dp_compute_m_n(intel_crtc->bpp, lane_count, -			     mode->clock, adjusted_mode->clock, &m_n); +	intel_link_compute_m_n(intel_crtc->bpp, lane_count, +			       mode->clock, adjusted_mode->clock, &m_n);  	if (IS_HASWELL(dev)) {  		I915_WRITE(PIPE_DATA_M1(cpu_transcoder), @@ -851,6 +866,32 @@ void intel_dp_init_link_config(struct intel_dp *intel_dp)  	}  } +static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	u32 dpa_ctl; + +	DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock); +	dpa_ctl = I915_READ(DP_A); +	dpa_ctl &= ~DP_PLL_FREQ_MASK; + +	if (clock < 200000) { +		/* For a long time we've carried around a ILK-DevA w/a for the +		 * 160MHz clock. If we're really unlucky, it's still required. +		 */ +		DRM_DEBUG_KMS("160MHz cpu eDP clock, might need ilk devA w/a\n"); +		dpa_ctl |= DP_PLL_FREQ_160MHZ; +	} else { +		dpa_ctl |= DP_PLL_FREQ_270MHZ; +	} + +	I915_WRITE(DP_A, dpa_ctl); + +	POSTING_READ(DP_A); +	udelay(500); +} +  static void  intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  		  struct drm_display_mode *adjusted_mode) @@ -950,6 +991,9 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  	} else {  		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;  	} + +	if (is_cpu_edp(intel_dp)) +		ironlake_set_pll_edp(crtc, adjusted_mode->clock);  }  #define IDLE_ON_MASK		(PP_ON | 0 	  | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK) @@ -1543,7 +1587,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST  }  static uint32_t -intel_dp_signal_levels(uint8_t train_set) +intel_gen4_signal_levels(uint8_t train_set)  {  	uint32_t	signal_levels = 0; @@ -1641,7 +1685,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_dp_signal_levels_hsw(uint8_t train_set) +intel_hsw_signal_levels(uint8_t train_set)  {  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -1673,6 +1717,34 @@ intel_dp_signal_levels_hsw(uint8_t train_set)  	}  } +/* Properly updates "DP" with the correct signal levels. */ +static void +intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) +{ +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); +	struct drm_device *dev = intel_dig_port->base.base.dev; +	uint32_t signal_levels, mask; +	uint8_t train_set = intel_dp->train_set[0]; + +	if (IS_HASWELL(dev)) { +		signal_levels = intel_hsw_signal_levels(train_set); +		mask = DDI_BUF_EMP_MASK; +	} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { +		signal_levels = intel_gen7_edp_signal_levels(train_set); +		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; +	} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { +		signal_levels = intel_gen6_edp_signal_levels(train_set); +		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; +	} else { +		signal_levels = intel_gen4_signal_levels(train_set); +		mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK; +	} + +	DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels); + +	*DP = (*DP & ~mask) | signal_levels; +} +  static bool  intel_dp_set_link_train(struct intel_dp *intel_dp,  			uint32_t dp_reg_value, @@ -1791,7 +1863,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  	int voltage_tries, loop_tries;  	uint32_t DP = intel_dp->DP; -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		intel_ddi_prepare_link_retrain(encoder);  	/* Write the link configuration data */ @@ -1809,24 +1881,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  	for (;;) {  		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */  		uint8_t	    link_status[DP_LINK_STATUS_SIZE]; -		uint32_t    signal_levels; -		if (IS_HASWELL(dev)) { -			signal_levels = intel_dp_signal_levels_hsw( -							intel_dp->train_set[0]); -			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels; -		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { -			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; -		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { -			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; -		} else { -			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; -		} -		DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", -			      signal_levels); +		intel_dp_set_signal_levels(intel_dp, &DP);  		/* Set training pattern 1 */  		if (!intel_dp_set_link_train(intel_dp, DP, @@ -1882,7 +1938,6 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  void  intel_dp_complete_link_train(struct intel_dp *intel_dp)  { -	struct drm_device *dev = intel_dp_to_dev(intel_dp);  	bool channel_eq = false;  	int tries, cr_tries;  	uint32_t DP = intel_dp->DP; @@ -1892,8 +1947,6 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  	cr_tries = 0;  	channel_eq = false;  	for (;;) { -		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ -		uint32_t    signal_levels;  		uint8_t	    link_status[DP_LINK_STATUS_SIZE];  		if (cr_tries > 5) { @@ -1902,19 +1955,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  			break;  		} -		if (IS_HASWELL(dev)) { -			signal_levels = intel_dp_signal_levels_hsw(intel_dp->train_set[0]); -			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels; -		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { -			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; -		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { -			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; -		} else { -			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; -		} +		intel_dp_set_signal_levels(intel_dp, &DP);  		/* channel eq pattern */  		if (!intel_dp_set_link_train(intel_dp, DP, @@ -1964,6 +2005,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	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; +	struct intel_crtc *intel_crtc = +		to_intel_crtc(intel_dig_port->base.base.crtc);  	uint32_t DP = intel_dp->DP;  	/* @@ -1981,7 +2024,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	 *   intel_ddi_prepare_link_retrain will take care of redoing the link  	 *   train.  	 */ -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		return;  	if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)) @@ -1998,7 +2041,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	}  	POSTING_READ(intel_dp->output_reg); -	msleep(17); +	/* We don't really know why we're doing this */ +	intel_wait_for_vblank(dev, intel_crtc->pipe);  	if (HAS_PCH_IBX(dev) &&  	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { @@ -2018,19 +2062,14 @@ intel_dp_link_down(struct intel_dp *intel_dp)  		/* Changes to enable or select take place the vblank  		 * after being written.  		 */ -		if (crtc == NULL) { -			/* We can arrive here never having been attached -			 * to a CRTC, for instance, due to inheriting -			 * random state from the BIOS. -			 * -			 * If the pipe is not running, play safe and -			 * wait for the clocks to stabilise before -			 * continuing. -			 */ +		if (WARN_ON(crtc == NULL)) { +			/* We should never try to disable a port without a crtc +			 * attached. For paranoia keep the code around for a +			 * bit. */  			POSTING_READ(intel_dp->output_reg);  			msleep(50);  		} else -			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); +			intel_wait_for_vblank(dev, intel_crtc->pipe);  	}  	DP &= ~DP_AUDIO_OUTPUT_ENABLE; @@ -2042,10 +2081,16 @@ intel_dp_link_down(struct intel_dp *intel_dp)  static bool  intel_dp_get_dpcd(struct intel_dp *intel_dp)  { +	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3]; +  	if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,  					   sizeof(intel_dp->dpcd)) == 0)  		return false; /* aux transfer failed */ +	hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd), +			   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false); +	DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump); +  	if (intel_dp->dpcd[DP_DPCD_REV] == 0)  		return false; /* DPCD not present */ @@ -2206,6 +2251,8 @@ static enum drm_connector_status  ironlake_dp_detect(struct intel_dp *intel_dp)  {  	struct drm_device *dev = intel_dp_to_dev(intel_dp); +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	enum drm_connector_status status;  	/* Can't disconnect eDP, but you can close the lid... */ @@ -2216,6 +2263,9 @@ ironlake_dp_detect(struct intel_dp *intel_dp)  		return status;  	} +	if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) +		return connector_status_disconnected; +  	return intel_dp_detect_dpcd(intel_dp);  } @@ -2290,13 +2340,6 @@ intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *ada  	return intel_ddc_get_modes(connector, adapter);  } - -/** - * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. - * - * \return true if DP port is connected. - * \return false if DP port is disconnected. - */  static enum drm_connector_status  intel_dp_detect(struct drm_connector *connector, bool force)  { @@ -2306,7 +2349,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)  	struct drm_device *dev = connector->dev;  	enum drm_connector_status status;  	struct edid *edid = NULL; -	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];  	intel_dp->has_audio = false; @@ -2315,10 +2357,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)  	else  		status = g4x_dp_detect(intel_dp); -	hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd), -			   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false); -	DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump); -  	if (status != connector_status_connected)  		return status; @@ -2445,11 +2483,8 @@ intel_dp_set_property(struct drm_connector *connector,  	return -EINVAL;  done: -	if (intel_encoder->base.crtc) { -		struct drm_crtc *crtc = intel_encoder->base.crtc; -		intel_set_mode(crtc, &crtc->mode, -			       crtc->x, crtc->y, crtc->fb); -	} +	if (intel_encoder->base.crtc) +		intel_crtc_restore_mode(intel_encoder->base.crtc);  	return 0;  } @@ -2742,7 +2777,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,  	intel_connector_attach_encoder(intel_connector, intel_encoder);  	drm_sysfs_connector_add(connector); -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;  	else  		intel_connector->get_hw_state = intel_connector_get_hw_state;  |