[Intel-gfx] [PATCH]DRM/IGD: Support IGD EOS - takes 2

Eric Anholt eric at anholt.net
Fri Sep 4 21:40:44 CEST 2009


On Fri, 2009-09-04 at 13:09 +0800, Shaohua Li wrote:
> In the event that any one of the DAC analog outputs (R,G,B) were driven
> at full-scale (white video) or some analog level close to full-scale
> voltage, and if the video cable were then disconnected, the analog video
> voltage level would exceed the maximum electrical overstress limit of the
> native (thin-oxide) transistors thus causing a long-term reliability concern.
> The electrical overstress condition occurs in this particular case.
> 
> This patch address the IGD EOS (electrical overstress condition) issue.
> When the EOS interrupt occurs, OS should disable DAC and then disable EOS,
> then the normal hotplug operation follows.
> 
> Signed-off-by: Shaohua Li <shaohua.li at intel.com>

The patch was already applied to -next, please supply updates in the
form of patches.

> ---
>  drivers/gpu/drm/i915/i915_drv.h  |    1 
>  drivers/gpu/drm/i915/i915_irq.c  |   16 +++++++
>  drivers/gpu/drm/i915/i915_reg.h  |    2 
>  drivers/gpu/drm/i915/intel_crt.c |   83 ++++++++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/intel_drv.h |    1 
>  5 files changed, 96 insertions(+), 7 deletions(-)
> 
> Index: linux/drivers/gpu/drm/i915/i915_reg.h
> ===================================================================
> --- linux.orig/drivers/gpu/drm/i915/i915_reg.h	2009-09-03 13:58:41.000000000 +0800
> +++ linux/drivers/gpu/drm/i915/i915_reg.h	2009-09-03 14:01:10.000000000 +0800
> @@ -683,6 +683,7 @@
>  #define   SDVOB_HOTPLUG_INT_EN			(1 << 26)
>  #define   SDVOC_HOTPLUG_INT_EN			(1 << 25)
>  #define   TV_HOTPLUG_INT_EN			(1 << 18)
> +#define   CRT_EOS_INT_EN			(1 << 10)
>  #define   CRT_HOTPLUG_INT_EN			(1 << 9)
>  #define   CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
>  #define CRT_HOTPLUG_ACTIVATION_PERIOD_32	(0 << 8)
> @@ -717,6 +718,7 @@
>  #define   DPC_HOTPLUG_INT_STATUS		(1 << 28)
>  #define   HDMID_HOTPLUG_INT_STATUS		(1 << 27)
>  #define   DPD_HOTPLUG_INT_STATUS		(1 << 27)
> +#define   CRT_EOS_INT_STATUS			(1 << 12)
>  #define   CRT_HOTPLUG_INT_STATUS		(1 << 11)
>  #define   TV_HOTPLUG_INT_STATUS			(1 << 10)
>  #define   CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
> Index: linux/drivers/gpu/drm/i915/i915_irq.c
> ===================================================================
> --- linux.orig/drivers/gpu/drm/i915/i915_irq.c	2009-09-03 13:58:41.000000000 +0800
> +++ linux/drivers/gpu/drm/i915/i915_irq.c	2009-09-03 14:01:10.000000000 +0800
> @@ -237,6 +237,11 @@ static void i915_hotplug_work_func(struc
>  	struct drm_mode_config *mode_config = &dev->mode_config;
>  	struct drm_connector *connector;
>  
> +	intel_igd_handle_eos(dev, dev_priv->hotplug_status);
> +
> +	if (!(dev_priv->hotplug_status & dev_priv->hotplug_supported_mask))
> +		return;
> +
>  	if (mode_config->num_connector) {
>  		list_for_each_entry(connector, &mode_config->connector_list, head) {
>  			struct intel_output *intel_output = to_intel_output(connector);
> @@ -557,9 +562,11 @@ irqreturn_t i915_driver_irq_handler(DRM_
>  		    (iir & I915_DISPLAY_PORT_INTERRUPT)) {
>  			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
>  
> +			dev_priv->hotplug_status = hotplug_status;
>  			DRM_DEBUG("hotplug event received, stat 0x%08x\n",
>  				  hotplug_status);
> -			if (hotplug_status & dev_priv->hotplug_supported_mask)
> +			if ((hotplug_status & dev_priv->hotplug_supported_mask) ||
> +			   (IS_IGD(dev) && (hotplug_status & CRT_EOS_INT_STATUS)))
>  				queue_work(dev_priv->wq,
>  					   &dev_priv->hotplug_work);
>  
> @@ -960,6 +967,13 @@ int i915_driver_irq_postinstall(struct d
>  		hotplug_en |= HOTPLUG_EN_MASK;
>  		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
>  
> +		/*
> +		 * The pipe select needs to be 1 when CRT Hot plug Interrupt
> +		 * Detection Enable is set when DAC is off under IGD
> +		 */
> +		if (IS_IGD(dev))
> +			I915_WRITE(ADPA, I915_READ(ADPA) | ADPA_PIPE_B_SELECT);
> +
>  		dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
>  			TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
>  			SDVOB_HOTPLUG_INT_STATUS;
> Index: linux/drivers/gpu/drm/i915/intel_crt.c
> ===================================================================
> --- linux.orig/drivers/gpu/drm/i915/intel_crt.c	2009-09-03 13:58:41.000000000 +0800
> +++ linux/drivers/gpu/drm/i915/intel_crt.c	2009-09-03 14:15:44.000000000 +0800
> @@ -60,10 +60,45 @@ static void intel_crt_dpms(struct drm_en
>  		break;
>  	case DRM_MODE_DPMS_OFF:
>  		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
> +
> +		/*
> +		 * The pipe select needs to be 1 when CRT Hot plug Interrupt
> +		 * Detection Enable is set when DAC is off under IGD
> +		 */
> +		if (IS_IGD(dev))
> +			temp |= ADPA_PIPE_B_SELECT;
>  		break;
>  	}
>  
>  	I915_WRITE(reg, temp);
> +
> +	if (IS_IGD(dev)) {
> +		if (mode == DRM_MODE_DPMS_OFF) {
> +			/* turn off DAC */
> +			temp = I915_READ(PORT_HOTPLUG_EN);
> +			temp &= ~CRT_EOS_INT_EN;
> +			I915_WRITE(PORT_HOTPLUG_EN, temp);
> +
> +			temp = I915_READ(PORT_HOTPLUG_STAT);
> +			if (temp & CRT_EOS_INT_STATUS)
> +				I915_WRITE(PORT_HOTPLUG_STAT,
> +					CRT_EOS_INT_STATUS);
> +		} else {
> +			/* turn on DAC. EOS interrupt must be enabled after DAC
> +			 * is enabled, so it sounds not good to enable it in
> +			 * i915_driver_irq_postinstall()
> +			 * wait 12.5ms after DAC is enabled
> +			 */
> +			msleep(13);
> +			temp = I915_READ(PORT_HOTPLUG_STAT);
> +			if (temp & CRT_EOS_INT_STATUS)
> +				I915_WRITE(PORT_HOTPLUG_STAT,
> +					CRT_EOS_INT_STATUS);
> +			temp = I915_READ(PORT_HOTPLUG_EN);
> +			temp |= CRT_EOS_INT_EN;
> +			I915_WRITE(PORT_HOTPLUG_EN, temp);
> +		}
> +	}
>  }
>  
>  static int intel_crt_mode_valid(struct drm_connector *connector,
> @@ -134,6 +169,7 @@ static void intel_crt_mode_set(struct dr
>  	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
>  		adpa |= ADPA_VSYNC_ACTIVE_HIGH;
>  
> +	adpa &= ~ADPA_PIPE_B_SELECT;
>  	if (intel_crtc->pipe == 0) {
>  		adpa |= ADPA_PIPE_A_SELECT;
>  		if (!IS_IGDNG(dev))
> @@ -147,9 +183,8 @@ static void intel_crt_mode_set(struct dr
>  	I915_WRITE(adpa_reg, adpa);
>  }
>  
> -static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
> +static bool intel_igdng_crt_detect_hotplug(struct drm_device *dev)
>  {
> -	struct drm_device *dev = connector->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 adpa, temp;
>  	bool ret;
> @@ -197,15 +232,14 @@ static bool intel_igdng_crt_detect_hotpl
>   * \return true if CRT is connected.
>   * \return false if CRT is disconnected.
>   */
> -static bool intel_crt_detect_hotplug(struct drm_connector *connector)
> +static bool intel_crt_detect_hotplug(struct drm_device *dev)
>  {
> -	struct drm_device *dev = connector->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 hotplug_en;
>  	int i, tries = 0;
>  
>  	if (IS_IGDNG(dev))
> -		return intel_igdng_crt_detect_hotplug(connector);
> +		return intel_igdng_crt_detect_hotplug(dev);
>  
>  	/*
>  	 * On 4 series desktop, CRT detect sequence need to be done twice
> @@ -246,6 +280,43 @@ static bool intel_crt_detect_hotplug(str
>  	return false;
>  }
>  
> +void intel_igd_handle_eos(struct drm_device *dev, u32 hotplug_status)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 temp;
> +	bool connected;
> +
> +	/* EOS interrupts occurs */
> +	if (IS_IGD(dev) && (hotplug_status & CRT_EOS_INT_STATUS)) {
> +
> +		mutex_lock(&dev->mode_config.mutex);
> +		connected = intel_crt_detect_hotplug(dev);
> +		DRM_DEBUG("EOS interrupt occurs, VGA is %s\n",
> +			connected ? "connected":"disconnected");
> +
> +		temp = I915_READ(PORT_HOTPLUG_STAT);
> +		if (temp & CRT_EOS_INT_STATUS)
> +			I915_WRITE(PORT_HOTPLUG_STAT, CRT_EOS_INT_STATUS);
> +		if (connected) {
> +			mutex_unlock(&dev->mode_config.mutex);
> +			return;
> +		}
> +
> +		temp = I915_READ(ADPA);
> +		temp &= ~ADPA_DAC_ENABLE;
> +		I915_WRITE(ADPA, temp);
> +
> +		temp = I915_READ(PORT_HOTPLUG_EN);
> +		temp &= ~CRT_EOS_INT_EN;
> +		I915_WRITE(PORT_HOTPLUG_EN, temp);
> +
> +		temp = I915_READ(PORT_HOTPLUG_STAT);
> +		if (temp & CRT_EOS_INT_STATUS)
> +			I915_WRITE(PORT_HOTPLUG_STAT, CRT_EOS_INT_STATUS);
> +		mutex_unlock(&dev->mode_config.mutex);
> +	}
> +}
> +
>  static bool intel_crt_detect_ddc(struct drm_connector *connector)
>  {
>  	struct intel_output *intel_output = to_intel_output(connector);
> @@ -395,7 +466,7 @@ static enum drm_connector_status intel_c
>  	enum drm_connector_status status;
>  
>  	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
> -		if (intel_crt_detect_hotplug(connector))
> +		if (intel_crt_detect_hotplug(dev))
>  			return connector_status_connected;
>  		else
>  			return connector_status_disconnected;
> Index: linux/drivers/gpu/drm/i915/intel_drv.h
> ===================================================================
> --- linux.orig/drivers/gpu/drm/i915/intel_drv.h	2009-09-03 13:58:41.000000000 +0800
> +++ linux/drivers/gpu/drm/i915/intel_drv.h	2009-09-03 14:01:10.000000000 +0800
> @@ -177,4 +177,5 @@ extern int intel_framebuffer_create(stru
>  				    struct drm_mode_fb_cmd *mode_cmd,
>  				    struct drm_framebuffer **fb,
>  				    struct drm_gem_object *obj);
> +extern void intel_igd_handle_eos(struct drm_device *dev, u32 hotplug_status);
>  #endif /* __INTEL_DRV_H__ */
> Index: linux/drivers/gpu/drm/i915/i915_drv.h
> ===================================================================
> --- linux.orig/drivers/gpu/drm/i915/i915_drv.h	2009-09-03 13:58:41.000000000 +0800
> +++ linux/drivers/gpu/drm/i915/i915_drv.h	2009-09-03 14:01:10.000000000 +0800
> @@ -190,6 +190,7 @@ typedef struct drm_i915_private {
>  	u32 de_irq_enable_reg;
>  
>  	u32 hotplug_supported_mask;
> +	u32 hotplug_status;
>  	struct work_struct hotplug_work;
>  
>  	int tex_lru_log_granularity;
-- 
Eric Anholt
eric at anholt.net                         eric.anholt at intel.com


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20090904/2009c899/attachment.sig>


More information about the Intel-gfx mailing list