diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 132 |
1 files changed, 75 insertions, 57 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 85f4c5de97e2..a17d6bdfe63e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
| 274 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 274 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 275 | int ret = IRQ_NONE; | 275 | int ret = IRQ_NONE; |
| 276 | u32 de_iir, gt_iir, de_ier, pch_iir; | 276 | u32 de_iir, gt_iir, de_ier, pch_iir; |
| 277 | u32 new_de_iir, new_gt_iir, new_pch_iir; | ||
| 278 | struct drm_i915_master_private *master_priv; | 277 | struct drm_i915_master_private *master_priv; |
| 279 | 278 | ||
| 280 | /* disable master interrupt before clearing iir */ | 279 | /* disable master interrupt before clearing iir */ |
| @@ -286,49 +285,58 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
| 286 | gt_iir = I915_READ(GTIIR); | 285 | gt_iir = I915_READ(GTIIR); |
| 287 | pch_iir = I915_READ(SDEIIR); | 286 | pch_iir = I915_READ(SDEIIR); |
| 288 | 287 | ||
| 289 | for (;;) { | 288 | if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) |
| 290 | if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) | 289 | goto done; |
| 291 | break; | ||
| 292 | 290 | ||
| 293 | ret = IRQ_HANDLED; | 291 | ret = IRQ_HANDLED; |
| 294 | 292 | ||
| 295 | /* should clear PCH hotplug event before clear CPU irq */ | 293 | if (dev->primary->master) { |
| 296 | I915_WRITE(SDEIIR, pch_iir); | 294 | master_priv = dev->primary->master->driver_priv; |
| 297 | new_pch_iir = I915_READ(SDEIIR); | 295 | if (master_priv->sarea_priv) |
| 296 | master_priv->sarea_priv->last_dispatch = | ||
| 297 | READ_BREADCRUMB(dev_priv); | ||
| 298 | } | ||
| 298 | 299 | ||
| 299 | I915_WRITE(DEIIR, de_iir); | 300 | if (gt_iir & GT_USER_INTERRUPT) { |
| 300 | new_de_iir = I915_READ(DEIIR); | 301 | u32 seqno = i915_get_gem_seqno(dev); |
| 301 | I915_WRITE(GTIIR, gt_iir); | 302 | dev_priv->mm.irq_gem_seqno = seqno; |
| 302 | new_gt_iir = I915_READ(GTIIR); | 303 | trace_i915_gem_request_complete(dev, seqno); |
| 304 | DRM_WAKEUP(&dev_priv->irq_queue); | ||
| 305 | dev_priv->hangcheck_count = 0; | ||
| 306 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | ||
| 307 | } | ||
| 303 | 308 | ||
| 304 | if (dev->primary->master) { | 309 | if (de_iir & DE_GSE) |
| 305 | master_priv = dev->primary->master->driver_priv; | 310 | ironlake_opregion_gse_intr(dev); |
| 306 | if (master_priv->sarea_priv) | ||
| 307 | master_priv->sarea_priv->last_dispatch = | ||
| 308 | READ_BREADCRUMB(dev_priv); | ||
| 309 | } | ||
| 310 | 311 | ||
| 311 | if (gt_iir & GT_USER_INTERRUPT) { | 312 | if (de_iir & DE_PLANEA_FLIP_DONE) { |
| 312 | u32 seqno = i915_get_gem_seqno(dev); | 313 | intel_prepare_page_flip(dev, 0); |
| 313 | dev_priv->mm.irq_gem_seqno = seqno; | 314 | intel_finish_page_flip(dev, 0); |
| 314 | trace_i915_gem_request_complete(dev, seqno); | 315 | } |
| 315 | DRM_WAKEUP(&dev_priv->irq_queue); | ||
| 316 | } | ||
| 317 | 316 | ||
| 318 | if (de_iir & DE_GSE) | 317 | if (de_iir & DE_PLANEB_FLIP_DONE) { |
| 319 | ironlake_opregion_gse_intr(dev); | 318 | intel_prepare_page_flip(dev, 1); |
| 319 | intel_finish_page_flip(dev, 1); | ||
| 320 | } | ||
| 320 | 321 | ||
| 321 | /* check event from PCH */ | 322 | if (de_iir & DE_PIPEA_VBLANK) |
| 322 | if ((de_iir & DE_PCH_EVENT) && | 323 | drm_handle_vblank(dev, 0); |
| 323 | (pch_iir & SDE_HOTPLUG_MASK)) { | ||
| 324 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | ||
| 325 | } | ||
| 326 | 324 | ||
| 327 | de_iir = new_de_iir; | 325 | if (de_iir & DE_PIPEB_VBLANK) |
| 328 | gt_iir = new_gt_iir; | 326 | drm_handle_vblank(dev, 1); |
| 329 | pch_iir = new_pch_iir; | 327 | |
| 328 | /* check event from PCH */ | ||
| 329 | if ((de_iir & DE_PCH_EVENT) && | ||
| 330 | (pch_iir & SDE_HOTPLUG_MASK)) { | ||
| 331 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | ||
| 330 | } | 332 | } |
| 331 | 333 | ||
| 334 | /* should clear PCH hotplug event before clear CPU irq */ | ||
| 335 | I915_WRITE(SDEIIR, pch_iir); | ||
| 336 | I915_WRITE(GTIIR, gt_iir); | ||
| 337 | I915_WRITE(DEIIR, de_iir); | ||
| 338 | |||
| 339 | done: | ||
| 332 | I915_WRITE(DEIER, de_ier); | 340 | I915_WRITE(DEIER, de_ier); |
| 333 | (void)I915_READ(DEIER); | 341 | (void)I915_READ(DEIER); |
| 334 | 342 | ||
| @@ -852,11 +860,11 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) | |||
| 852 | if (!(pipeconf & PIPEACONF_ENABLE)) | 860 | if (!(pipeconf & PIPEACONF_ENABLE)) |
| 853 | return -EINVAL; | 861 | return -EINVAL; |
| 854 | 862 | ||
| 855 | if (IS_IRONLAKE(dev)) | ||
| 856 | return 0; | ||
| 857 | |||
| 858 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 863 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
| 859 | if (IS_I965G(dev)) | 864 | if (IS_IRONLAKE(dev)) |
| 865 | ironlake_enable_display_irq(dev_priv, (pipe == 0) ? | ||
| 866 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | ||
| 867 | else if (IS_I965G(dev)) | ||
| 860 | i915_enable_pipestat(dev_priv, pipe, | 868 | i915_enable_pipestat(dev_priv, pipe, |
| 861 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | 869 | PIPE_START_VBLANK_INTERRUPT_ENABLE); |
| 862 | else | 870 | else |
| @@ -874,13 +882,14 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) | |||
| 874 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 882 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 875 | unsigned long irqflags; | 883 | unsigned long irqflags; |
| 876 | 884 | ||
| 877 | if (IS_IRONLAKE(dev)) | ||
| 878 | return; | ||
| 879 | |||
| 880 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 885 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
| 881 | i915_disable_pipestat(dev_priv, pipe, | 886 | if (IS_IRONLAKE(dev)) |
| 882 | PIPE_VBLANK_INTERRUPT_ENABLE | | 887 | ironlake_disable_display_irq(dev_priv, (pipe == 0) ? |
| 883 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | 888 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); |
| 889 | else | ||
| 890 | i915_disable_pipestat(dev_priv, pipe, | ||
| 891 | PIPE_VBLANK_INTERRUPT_ENABLE | | ||
| 892 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | ||
| 884 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); | 893 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); |
| 885 | } | 894 | } |
| 886 | 895 | ||
| @@ -1023,13 +1032,14 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
| 1023 | { | 1032 | { |
| 1024 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1033 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 1025 | /* enable kind of interrupts always enabled */ | 1034 | /* enable kind of interrupts always enabled */ |
| 1026 | u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT; | 1035 | u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | |
| 1036 | DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE; | ||
| 1027 | u32 render_mask = GT_USER_INTERRUPT; | 1037 | u32 render_mask = GT_USER_INTERRUPT; |
| 1028 | u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | | 1038 | u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | |
| 1029 | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; | 1039 | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; |
| 1030 | 1040 | ||
| 1031 | dev_priv->irq_mask_reg = ~display_mask; | 1041 | dev_priv->irq_mask_reg = ~display_mask; |
| 1032 | dev_priv->de_irq_enable_reg = display_mask; | 1042 | dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK; |
| 1033 | 1043 | ||
| 1034 | /* should always can generate irq */ | 1044 | /* should always can generate irq */ |
| 1035 | I915_WRITE(DEIIR, I915_READ(DEIIR)); | 1045 | I915_WRITE(DEIIR, I915_READ(DEIIR)); |
| @@ -1084,6 +1094,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev) | |||
| 1084 | (void) I915_READ(IER); | 1094 | (void) I915_READ(IER); |
| 1085 | } | 1095 | } |
| 1086 | 1096 | ||
| 1097 | /* | ||
| 1098 | * Must be called after intel_modeset_init or hotplug interrupts won't be | ||
| 1099 | * enabled correctly. | ||
| 1100 | */ | ||
| 1087 | int i915_driver_irq_postinstall(struct drm_device *dev) | 1101 | int i915_driver_irq_postinstall(struct drm_device *dev) |
| 1088 | { | 1102 | { |
| 1089 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1103 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| @@ -1106,19 +1120,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
| 1106 | if (I915_HAS_HOTPLUG(dev)) { | 1120 | if (I915_HAS_HOTPLUG(dev)) { |
| 1107 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); | 1121 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); |
| 1108 | 1122 | ||
| 1109 | /* Leave other bits alone */ | 1123 | /* Note HDMI and DP share bits */ |
| 1110 | hotplug_en |= HOTPLUG_EN_MASK; | 1124 | if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) |
| 1125 | hotplug_en |= HDMIB_HOTPLUG_INT_EN; | ||
| 1126 | if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) | ||
| 1127 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; | ||
| 1128 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) | ||
| 1129 | hotplug_en |= HDMID_HOTPLUG_INT_EN; | ||
| 1130 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) | ||
| 1131 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | ||
| 1132 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) | ||
| 1133 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | ||
| 1134 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) | ||
| 1135 | hotplug_en |= CRT_HOTPLUG_INT_EN; | ||
| 1136 | /* Ignore TV since it's buggy */ | ||
| 1137 | |||
| 1111 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); | 1138 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); |
| 1112 | 1139 | ||
| 1113 | dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS | | ||
| 1114 | TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS | | ||
| 1115 | SDVOB_HOTPLUG_INT_STATUS; | ||
| 1116 | if (IS_G4X(dev)) { | ||
| 1117 | dev_priv->hotplug_supported_mask |= | ||
| 1118 | HDMIB_HOTPLUG_INT_STATUS | | ||
| 1119 | HDMIC_HOTPLUG_INT_STATUS | | ||
| 1120 | HDMID_HOTPLUG_INT_STATUS; | ||
| 1121 | } | ||
| 1122 | /* Enable in IER... */ | 1140 | /* Enable in IER... */ |
| 1123 | enable_mask |= I915_DISPLAY_PORT_INTERRUPT; | 1141 | enable_mask |= I915_DISPLAY_PORT_INTERRUPT; |
| 1124 | /* and unmask in IMR */ | 1142 | /* and unmask in IMR */ |
