|
@@ -36,6 +36,59 @@
|
|
|
#include "i915_trace.h"
|
|
|
#include "intel_drv.h"
|
|
|
|
|
|
+static const u32 hpd_ibx[] = {
|
|
|
+ [HPD_CRT] = SDE_CRT_HOTPLUG,
|
|
|
+ [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
|
|
|
+ [HPD_PORT_B] = SDE_PORTB_HOTPLUG,
|
|
|
+ [HPD_PORT_C] = SDE_PORTC_HOTPLUG,
|
|
|
+ [HPD_PORT_D] = SDE_PORTD_HOTPLUG
|
|
|
+};
|
|
|
+
|
|
|
+static const u32 hpd_cpt[] = {
|
|
|
+ [HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
|
|
|
+ [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
|
|
|
+ [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
|
|
|
+ [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
|
|
|
+};
|
|
|
+
|
|
|
+static const u32 hpd_mask_i915[] = {
|
|
|
+ [HPD_CRT] = CRT_HOTPLUG_INT_EN,
|
|
|
+ [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
|
|
|
+ [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
|
|
|
+ [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
|
|
|
+ [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
|
|
|
+ [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
|
|
|
+};
|
|
|
+
|
|
|
+static const u32 hpd_status_gen4[] = {
|
|
|
+ [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
|
|
|
+ [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
|
|
|
+ [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
|
|
|
+};
|
|
|
+
|
|
|
+static const u32 hpd_status_i965[] = {
|
|
|
+ [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I965,
|
|
|
+ [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I965,
|
|
|
+ [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
|
|
|
+};
|
|
|
+
|
|
|
+static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
|
|
|
+ [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
|
|
|
+ [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
|
|
|
+ [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
|
|
|
+ [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
/* For display hotplug interrupt */
|
|
|
static void
|
|
|
ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
|
|
@@ -599,7 +652,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
|
|
|
|
|
|
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
|
|
|
hotplug_status);
|
|
|
- if (hotplug_status & dev_priv->hotplug_supported_mask)
|
|
|
+ if (hotplug_status & HOTPLUG_INT_STATUS_I915)
|
|
|
queue_work(dev_priv->wq,
|
|
|
&dev_priv->hotplug_work);
|
|
|
|
|
@@ -2034,17 +2087,21 @@ static void ibx_enable_hotplug(struct drm_device *dev)
|
|
|
static void ibx_irq_postinstall(struct drm_device *dev)
|
|
|
{
|
|
|
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
- u32 mask;
|
|
|
-
|
|
|
- if (HAS_PCH_IBX(dev))
|
|
|
- mask = SDE_HOTPLUG_MASK |
|
|
|
- SDE_GMBUS |
|
|
|
- SDE_AUX_MASK;
|
|
|
- else
|
|
|
- mask = SDE_HOTPLUG_MASK_CPT |
|
|
|
- SDE_GMBUS_CPT |
|
|
|
- SDE_AUX_MASK_CPT;
|
|
|
-
|
|
|
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
+ struct intel_encoder *intel_encoder;
|
|
|
+ u32 mask = I915_READ(SDEIER);
|
|
|
+
|
|
|
+ if (HAS_PCH_IBX(dev)) {
|
|
|
+ mask &= ~SDE_HOTPLUG_MASK;
|
|
|
+ list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
|
|
+ mask |= hpd_ibx[intel_encoder->hpd_pin];
|
|
|
+ mask |= SDE_GMBUS | SDE_AUX_MASK;
|
|
|
+ } else {
|
|
|
+ mask &= ~SDE_HOTPLUG_MASK_CPT;
|
|
|
+ list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
|
|
+ mask |= hpd_cpt[intel_encoder->hpd_pin];
|
|
|
+ mask |= SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
|
|
|
+ }
|
|
|
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
|
|
|
I915_WRITE(SDEIMR, ~mask);
|
|
|
I915_WRITE(SDEIER, mask);
|
|
@@ -2466,26 +2523,16 @@ static int i915_irq_postinstall(struct drm_device *dev)
|
|
|
|
|
|
static void i915_hpd_irq_setup(struct drm_device *dev)
|
|
|
{
|
|
|
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
- u32 hotplug_en;
|
|
|
-
|
|
|
if (I915_HAS_HOTPLUG(dev)) {
|
|
|
- hotplug_en = I915_READ(PORT_HOTPLUG_EN);
|
|
|
-
|
|
|
- if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
|
|
|
- hotplug_en |= PORTB_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
|
|
|
- hotplug_en |= PORTC_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
|
|
|
- hotplug_en |= PORTD_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
|
|
|
- hotplug_en |= SDVOC_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
|
|
|
- hotplug_en |= SDVOB_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
|
|
|
- hotplug_en |= CRT_HOTPLUG_INT_EN;
|
|
|
- hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
|
|
- }
|
|
|
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
+ struct intel_encoder *encoder;
|
|
|
+ u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
|
|
|
+
|
|
|
+ hotplug_en &= ~HOTPLUG_INT_EN_MASK;
|
|
|
+ list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
|
|
|
+ hotplug_en |= hpd_mask_i915[encoder->hpd_pin];
|
|
|
+ hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
|
|
|
|
|
/* Ignore TV since it's buggy */
|
|
|
|
|
@@ -2576,7 +2623,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|
|
|
|
|
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
|
|
|
hotplug_status);
|
|
|
- if (hotplug_status & dev_priv->hotplug_supported_mask)
|
|
|
+ if (hotplug_status & HOTPLUG_INT_STATUS_I915)
|
|
|
queue_work(dev_priv->wq,
|
|
|
&dev_priv->hotplug_work);
|
|
|
|
|
@@ -2725,38 +2772,22 @@ static int i965_irq_postinstall(struct drm_device *dev)
|
|
|
static void i965_hpd_irq_setup(struct drm_device *dev)
|
|
|
{
|
|
|
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
+ struct intel_encoder *encoder;
|
|
|
u32 hotplug_en;
|
|
|
|
|
|
/* Note HDMI and DP share hotplug bits */
|
|
|
hotplug_en = 0;
|
|
|
- if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
|
|
|
- hotplug_en |= PORTB_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
|
|
|
- hotplug_en |= PORTC_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
|
|
|
- hotplug_en |= PORTD_HOTPLUG_INT_EN;
|
|
|
- if (IS_G4X(dev)) {
|
|
|
- if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X)
|
|
|
- hotplug_en |= SDVOC_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X)
|
|
|
- hotplug_en |= SDVOB_HOTPLUG_INT_EN;
|
|
|
- } else {
|
|
|
- if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965)
|
|
|
- hotplug_en |= SDVOC_HOTPLUG_INT_EN;
|
|
|
- if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965)
|
|
|
- hotplug_en |= SDVOB_HOTPLUG_INT_EN;
|
|
|
- }
|
|
|
- if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
|
|
|
- hotplug_en |= CRT_HOTPLUG_INT_EN;
|
|
|
-
|
|
|
- /* Programming the CRT detection parameters tends
|
|
|
- to generate a spurious hotplug event about three
|
|
|
- seconds later. So just do it once.
|
|
|
- */
|
|
|
- if (IS_G4X(dev))
|
|
|
- hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
|
|
|
- hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
|
|
- }
|
|
|
+ list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
|
|
|
+ /* enable bits are the same for all generations */
|
|
|
+ hotplug_en |= hpd_mask_i915[encoder->hpd_pin];
|
|
|
+ /* Programming the CRT detection parameters tends
|
|
|
+ to generate a spurious hotplug event about three
|
|
|
+ seconds later. So just do it once.
|
|
|
+ */
|
|
|
+ if (IS_G4X(dev))
|
|
|
+ hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
|
|
|
+ hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
|
|
|
|
|
/* Ignore TV since it's buggy */
|
|
|
|
|
@@ -2822,7 +2853,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|
|
|
|
|
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
|
|
|
hotplug_status);
|
|
|
- if (hotplug_status & dev_priv->hotplug_supported_mask)
|
|
|
+ if (hotplug_status & (IS_G4X(dev) ?
|
|
|
+ HOTPLUG_INT_STATUS_G4X :
|
|
|
+ HOTPLUG_INT_STATUS_I965))
|
|
|
queue_work(dev_priv->wq,
|
|
|
&dev_priv->hotplug_work);
|
|
|
|