From patchwork Mon Sep 7 07:43:20 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shaohua Li X-Patchwork-Id: 46671 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8AMCxlx007295 for ; Thu, 10 Sep 2009 22:12:59 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CBC589F2FC; Mon, 7 Sep 2009 00:43:24 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 5D4599E81E for ; Mon, 7 Sep 2009 00:43:22 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 07 Sep 2009 00:39:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.44,345,1249282800"; d="scan'208";a="724528974" Received: from sli10-conroe.sh.intel.com (HELO sli10-desk.sh.intel.com) ([10.239.13.175]) by fmsmga001.fm.intel.com with ESMTP; 07 Sep 2009 00:46:23 -0700 Received: from david by sli10-desk.sh.intel.com with local (Exim 4.69) (envelope-from ) id 1MkYsi-0005Is-Sn; Mon, 07 Sep 2009 15:43:20 +0800 Date: Mon, 7 Sep 2009 15:43:20 +0800 From: Shaohua Li To: Eric Anholt Message-ID: <20090907074320.GA19224@sli10-desk.sh.intel.com> References: <20090904050923.GA15129@sli10-desk.sh.intel.com> <1252093244.1774.8.camel@gaiman.anholt.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1252093244.1774.8.camel@gaiman.anholt.net> User-Agent: Mutt/1.5.18 (2008-05-17) Cc: "intel-gfx@lists.freedesktop.org" , "Li, Peng" Subject: Re: [Intel-gfx] [PATCH]DRM/IGD: Support IGD EOS - takes 2 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org On Sat, Sep 05, 2009 at 03:40:44AM +0800, Eric Anholt wrote: > 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 > > The patch was already applied to -next, please supply updates in the > form of patches. Spec slightly changes the way to handle IGD EOS. This patch makes our driver align to latest spec. Signed-off-by: Shaohua Li --- drivers/gpu/drm/i915/i915_drv.h | 1 drivers/gpu/drm/i915/i915_irq.c | 37 ++++++++++---------------- drivers/gpu/drm/i915/intel_crt.c | 54 ++++++++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_drv.h | 1 4 files changed, 65 insertions(+), 28 deletions(-) Index: linux/drivers/gpu/drm/i915/i915_drv.h =================================================================== --- linux.orig/drivers/gpu/drm/i915/i915_drv.h 2009-09-07 15:16:44.000000000 +0800 +++ linux/drivers/gpu/drm/i915/i915_drv.h 2009-09-07 15:17:40.000000000 +0800 @@ -189,6 +189,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; Index: linux/drivers/gpu/drm/i915/i915_irq.c =================================================================== --- linux.orig/drivers/gpu/drm/i915/i915_irq.c 2009-09-07 15:16:15.000000000 +0800 +++ linux/drivers/gpu/drm/i915/i915_irq.c 2009-09-07 15:30:04.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,35 +562,16 @@ 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); I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); I915_READ(PORT_HOTPLUG_STAT); - - /* EOS interrupts occurs */ - if (IS_IGD(dev) && - (hotplug_status & CRT_EOS_INT_STATUS)) { - u32 temp; - - DRM_DEBUG("EOS interrupt occurs\n"); - /* status is already cleared */ - 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); - } } I915_WRITE(IIR, iir); @@ -981,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-07 15:15:16.000000000 +0800 +++ linux/drivers/gpu/drm/i915/intel_crt.c 2009-09-07 15:30:31.000000000 +0800 @@ -60,6 +60,13 @@ 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; } @@ -162,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)) @@ -175,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; @@ -225,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 @@ -274,6 +280,42 @@ 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); @@ -423,7 +465,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-07 15:16:02.000000000 +0800 +++ linux/drivers/gpu/drm/i915/intel_drv.h 2009-09-07 15:18:08.000000000 +0800 @@ -181,4 +181,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__ */