diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 311 |
1 files changed, 264 insertions, 47 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 188b497e5076..b79619a7b788 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -367,22 +367,30 @@ static void notify_ring(struct drm_device *dev, | |||
367 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | 367 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); |
368 | } | 368 | } |
369 | 369 | ||
370 | static void gen6_pm_irq_handler(struct drm_device *dev) | 370 | static void gen6_pm_rps_work(struct work_struct *work) |
371 | { | 371 | { |
372 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 372 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, |
373 | rps_work); | ||
373 | u8 new_delay = dev_priv->cur_delay; | 374 | u8 new_delay = dev_priv->cur_delay; |
374 | u32 pm_iir; | 375 | u32 pm_iir, pm_imr; |
376 | |||
377 | spin_lock_irq(&dev_priv->rps_lock); | ||
378 | pm_iir = dev_priv->pm_iir; | ||
379 | dev_priv->pm_iir = 0; | ||
380 | pm_imr = I915_READ(GEN6_PMIMR); | ||
381 | spin_unlock_irq(&dev_priv->rps_lock); | ||
375 | 382 | ||
376 | pm_iir = I915_READ(GEN6_PMIIR); | ||
377 | if (!pm_iir) | 383 | if (!pm_iir) |
378 | return; | 384 | return; |
379 | 385 | ||
386 | mutex_lock(&dev_priv->dev->struct_mutex); | ||
380 | if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { | 387 | if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { |
381 | if (dev_priv->cur_delay != dev_priv->max_delay) | 388 | if (dev_priv->cur_delay != dev_priv->max_delay) |
382 | new_delay = dev_priv->cur_delay + 1; | 389 | new_delay = dev_priv->cur_delay + 1; |
383 | if (new_delay > dev_priv->max_delay) | 390 | if (new_delay > dev_priv->max_delay) |
384 | new_delay = dev_priv->max_delay; | 391 | new_delay = dev_priv->max_delay; |
385 | } else if (pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT)) { | 392 | } else if (pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT)) { |
393 | gen6_gt_force_wake_get(dev_priv); | ||
386 | if (dev_priv->cur_delay != dev_priv->min_delay) | 394 | if (dev_priv->cur_delay != dev_priv->min_delay) |
387 | new_delay = dev_priv->cur_delay - 1; | 395 | new_delay = dev_priv->cur_delay - 1; |
388 | if (new_delay < dev_priv->min_delay) { | 396 | if (new_delay < dev_priv->min_delay) { |
@@ -396,13 +404,19 @@ static void gen6_pm_irq_handler(struct drm_device *dev) | |||
396 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | 404 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, |
397 | I915_READ(GEN6_RP_INTERRUPT_LIMITS) & ~0x3f0000); | 405 | I915_READ(GEN6_RP_INTERRUPT_LIMITS) & ~0x3f0000); |
398 | } | 406 | } |
399 | 407 | gen6_gt_force_wake_put(dev_priv); | |
400 | } | 408 | } |
401 | 409 | ||
402 | gen6_set_rps(dev, new_delay); | 410 | gen6_set_rps(dev_priv->dev, new_delay); |
403 | dev_priv->cur_delay = new_delay; | 411 | dev_priv->cur_delay = new_delay; |
404 | 412 | ||
405 | I915_WRITE(GEN6_PMIIR, pm_iir); | 413 | /* |
414 | * rps_lock not held here because clearing is non-destructive. There is | ||
415 | * an *extremely* unlikely race with gen6_rps_enable() that is prevented | ||
416 | * by holding struct_mutex for the duration of the write. | ||
417 | */ | ||
418 | I915_WRITE(GEN6_PMIMR, pm_imr & ~pm_iir); | ||
419 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
406 | } | 420 | } |
407 | 421 | ||
408 | static void pch_irq_handler(struct drm_device *dev) | 422 | static void pch_irq_handler(struct drm_device *dev) |
@@ -448,8 +462,97 @@ static void pch_irq_handler(struct drm_device *dev) | |||
448 | DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); | 462 | DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); |
449 | } | 463 | } |
450 | 464 | ||
451 | static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | 465 | irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) |
466 | { | ||
467 | struct drm_device *dev = (struct drm_device *) arg; | ||
468 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
469 | int ret = IRQ_NONE; | ||
470 | u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; | ||
471 | struct drm_i915_master_private *master_priv; | ||
472 | |||
473 | atomic_inc(&dev_priv->irq_received); | ||
474 | |||
475 | /* disable master interrupt before clearing iir */ | ||
476 | de_ier = I915_READ(DEIER); | ||
477 | I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); | ||
478 | POSTING_READ(DEIER); | ||
479 | |||
480 | de_iir = I915_READ(DEIIR); | ||
481 | gt_iir = I915_READ(GTIIR); | ||
482 | pch_iir = I915_READ(SDEIIR); | ||
483 | pm_iir = I915_READ(GEN6_PMIIR); | ||
484 | |||
485 | if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 && pm_iir == 0) | ||
486 | goto done; | ||
487 | |||
488 | ret = IRQ_HANDLED; | ||
489 | |||
490 | if (dev->primary->master) { | ||
491 | master_priv = dev->primary->master->driver_priv; | ||
492 | if (master_priv->sarea_priv) | ||
493 | master_priv->sarea_priv->last_dispatch = | ||
494 | READ_BREADCRUMB(dev_priv); | ||
495 | } | ||
496 | |||
497 | if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY)) | ||
498 | notify_ring(dev, &dev_priv->ring[RCS]); | ||
499 | if (gt_iir & GT_GEN6_BSD_USER_INTERRUPT) | ||
500 | notify_ring(dev, &dev_priv->ring[VCS]); | ||
501 | if (gt_iir & GT_BLT_USER_INTERRUPT) | ||
502 | notify_ring(dev, &dev_priv->ring[BCS]); | ||
503 | |||
504 | if (de_iir & DE_GSE_IVB) | ||
505 | intel_opregion_gse_intr(dev); | ||
506 | |||
507 | if (de_iir & DE_PLANEA_FLIP_DONE_IVB) { | ||
508 | intel_prepare_page_flip(dev, 0); | ||
509 | intel_finish_page_flip_plane(dev, 0); | ||
510 | } | ||
511 | |||
512 | if (de_iir & DE_PLANEB_FLIP_DONE_IVB) { | ||
513 | intel_prepare_page_flip(dev, 1); | ||
514 | intel_finish_page_flip_plane(dev, 1); | ||
515 | } | ||
516 | |||
517 | if (de_iir & DE_PIPEA_VBLANK_IVB) | ||
518 | drm_handle_vblank(dev, 0); | ||
519 | |||
520 | if (de_iir & DE_PIPEB_VBLANK_IVB); | ||
521 | drm_handle_vblank(dev, 1); | ||
522 | |||
523 | /* check event from PCH */ | ||
524 | if (de_iir & DE_PCH_EVENT_IVB) { | ||
525 | if (pch_iir & SDE_HOTPLUG_MASK_CPT) | ||
526 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | ||
527 | pch_irq_handler(dev); | ||
528 | } | ||
529 | |||
530 | if (pm_iir & GEN6_PM_DEFERRED_EVENTS) { | ||
531 | unsigned long flags; | ||
532 | spin_lock_irqsave(&dev_priv->rps_lock, flags); | ||
533 | WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); | ||
534 | I915_WRITE(GEN6_PMIMR, pm_iir); | ||
535 | dev_priv->pm_iir |= pm_iir; | ||
536 | spin_unlock_irqrestore(&dev_priv->rps_lock, flags); | ||
537 | queue_work(dev_priv->wq, &dev_priv->rps_work); | ||
538 | } | ||
539 | |||
540 | /* should clear PCH hotplug event before clear CPU irq */ | ||
541 | I915_WRITE(SDEIIR, pch_iir); | ||
542 | I915_WRITE(GTIIR, gt_iir); | ||
543 | I915_WRITE(DEIIR, de_iir); | ||
544 | I915_WRITE(GEN6_PMIIR, pm_iir); | ||
545 | |||
546 | done: | ||
547 | I915_WRITE(DEIER, de_ier); | ||
548 | POSTING_READ(DEIER); | ||
549 | |||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) | ||
452 | { | 554 | { |
555 | struct drm_device *dev = (struct drm_device *) arg; | ||
453 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 556 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
454 | int ret = IRQ_NONE; | 557 | int ret = IRQ_NONE; |
455 | u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; | 558 | u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; |
@@ -457,6 +560,8 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
457 | struct drm_i915_master_private *master_priv; | 560 | struct drm_i915_master_private *master_priv; |
458 | u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; | 561 | u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; |
459 | 562 | ||
563 | atomic_inc(&dev_priv->irq_received); | ||
564 | |||
460 | if (IS_GEN6(dev)) | 565 | if (IS_GEN6(dev)) |
461 | bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; | 566 | bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; |
462 | 567 | ||
@@ -526,13 +631,30 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
526 | i915_handle_rps_change(dev); | 631 | i915_handle_rps_change(dev); |
527 | } | 632 | } |
528 | 633 | ||
529 | if (IS_GEN6(dev)) | 634 | if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS) { |
530 | gen6_pm_irq_handler(dev); | 635 | /* |
636 | * IIR bits should never already be set because IMR should | ||
637 | * prevent an interrupt from being shown in IIR. The warning | ||
638 | * displays a case where we've unsafely cleared | ||
639 | * dev_priv->pm_iir. Although missing an interrupt of the same | ||
640 | * type is not a problem, it displays a problem in the logic. | ||
641 | * | ||
642 | * The mask bit in IMR is cleared by rps_work. | ||
643 | */ | ||
644 | unsigned long flags; | ||
645 | spin_lock_irqsave(&dev_priv->rps_lock, flags); | ||
646 | WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); | ||
647 | I915_WRITE(GEN6_PMIMR, pm_iir); | ||
648 | dev_priv->pm_iir |= pm_iir; | ||
649 | spin_unlock_irqrestore(&dev_priv->rps_lock, flags); | ||
650 | queue_work(dev_priv->wq, &dev_priv->rps_work); | ||
651 | } | ||
531 | 652 | ||
532 | /* should clear PCH hotplug event before clear CPU irq */ | 653 | /* should clear PCH hotplug event before clear CPU irq */ |
533 | I915_WRITE(SDEIIR, pch_iir); | 654 | I915_WRITE(SDEIIR, pch_iir); |
534 | I915_WRITE(GTIIR, gt_iir); | 655 | I915_WRITE(GTIIR, gt_iir); |
535 | I915_WRITE(DEIIR, de_iir); | 656 | I915_WRITE(DEIIR, de_iir); |
657 | I915_WRITE(GEN6_PMIIR, pm_iir); | ||
536 | 658 | ||
537 | done: | 659 | done: |
538 | I915_WRITE(DEIER, de_ier); | 660 | I915_WRITE(DEIER, de_ier); |
@@ -676,7 +798,7 @@ static u32 capture_bo_list(struct drm_i915_error_buffer *err, | |||
676 | err->dirty = obj->dirty; | 798 | err->dirty = obj->dirty; |
677 | err->purgeable = obj->madv != I915_MADV_WILLNEED; | 799 | err->purgeable = obj->madv != I915_MADV_WILLNEED; |
678 | err->ring = obj->ring ? obj->ring->id : 0; | 800 | err->ring = obj->ring ? obj->ring->id : 0; |
679 | err->agp_type = obj->agp_type == AGP_USER_CACHED_MEMORY; | 801 | err->cache_level = obj->cache_level; |
680 | 802 | ||
681 | if (++i == count) | 803 | if (++i == count) |
682 | break; | 804 | break; |
@@ -1103,9 +1225,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
1103 | 1225 | ||
1104 | atomic_inc(&dev_priv->irq_received); | 1226 | atomic_inc(&dev_priv->irq_received); |
1105 | 1227 | ||
1106 | if (HAS_PCH_SPLIT(dev)) | ||
1107 | return ironlake_irq_handler(dev); | ||
1108 | |||
1109 | iir = I915_READ(IIR); | 1228 | iir = I915_READ(IIR); |
1110 | 1229 | ||
1111 | if (INTEL_INFO(dev)->gen >= 4) | 1230 | if (INTEL_INFO(dev)->gen >= 4) |
@@ -1344,10 +1463,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) | |||
1344 | return -EINVAL; | 1463 | return -EINVAL; |
1345 | 1464 | ||
1346 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1465 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
1347 | if (HAS_PCH_SPLIT(dev)) | 1466 | if (INTEL_INFO(dev)->gen >= 4) |
1348 | ironlake_enable_display_irq(dev_priv, (pipe == 0) ? | ||
1349 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | ||
1350 | else if (INTEL_INFO(dev)->gen >= 4) | ||
1351 | i915_enable_pipestat(dev_priv, pipe, | 1467 | i915_enable_pipestat(dev_priv, pipe, |
1352 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | 1468 | PIPE_START_VBLANK_INTERRUPT_ENABLE); |
1353 | else | 1469 | else |
@@ -1362,6 +1478,38 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) | |||
1362 | return 0; | 1478 | return 0; |
1363 | } | 1479 | } |
1364 | 1480 | ||
1481 | int ironlake_enable_vblank(struct drm_device *dev, int pipe) | ||
1482 | { | ||
1483 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1484 | unsigned long irqflags; | ||
1485 | |||
1486 | if (!i915_pipe_enabled(dev, pipe)) | ||
1487 | return -EINVAL; | ||
1488 | |||
1489 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
1490 | ironlake_enable_display_irq(dev_priv, (pipe == 0) ? | ||
1491 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | ||
1492 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | int ivybridge_enable_vblank(struct drm_device *dev, int pipe) | ||
1498 | { | ||
1499 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1500 | unsigned long irqflags; | ||
1501 | |||
1502 | if (!i915_pipe_enabled(dev, pipe)) | ||
1503 | return -EINVAL; | ||
1504 | |||
1505 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
1506 | ironlake_enable_display_irq(dev_priv, (pipe == 0) ? | ||
1507 | DE_PIPEA_VBLANK_IVB : DE_PIPEB_VBLANK_IVB); | ||
1508 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
1509 | |||
1510 | return 0; | ||
1511 | } | ||
1512 | |||
1365 | /* Called from drm generic code, passed 'crtc' which | 1513 | /* Called from drm generic code, passed 'crtc' which |
1366 | * we use as a pipe index | 1514 | * we use as a pipe index |
1367 | */ | 1515 | */ |
@@ -1375,13 +1523,31 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) | |||
1375 | I915_WRITE(INSTPM, | 1523 | I915_WRITE(INSTPM, |
1376 | INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS); | 1524 | INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS); |
1377 | 1525 | ||
1378 | if (HAS_PCH_SPLIT(dev)) | 1526 | i915_disable_pipestat(dev_priv, pipe, |
1379 | ironlake_disable_display_irq(dev_priv, (pipe == 0) ? | 1527 | PIPE_VBLANK_INTERRUPT_ENABLE | |
1380 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | 1528 | PIPE_START_VBLANK_INTERRUPT_ENABLE); |
1381 | else | 1529 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
1382 | i915_disable_pipestat(dev_priv, pipe, | 1530 | } |
1383 | PIPE_VBLANK_INTERRUPT_ENABLE | | 1531 | |
1384 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | 1532 | void ironlake_disable_vblank(struct drm_device *dev, int pipe) |
1533 | { | ||
1534 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1535 | unsigned long irqflags; | ||
1536 | |||
1537 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
1538 | ironlake_disable_display_irq(dev_priv, (pipe == 0) ? | ||
1539 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | ||
1540 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
1541 | } | ||
1542 | |||
1543 | void ivybridge_disable_vblank(struct drm_device *dev, int pipe) | ||
1544 | { | ||
1545 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1546 | unsigned long irqflags; | ||
1547 | |||
1548 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
1549 | ironlake_disable_display_irq(dev_priv, (pipe == 0) ? | ||
1550 | DE_PIPEA_VBLANK_IVB : DE_PIPEB_VBLANK_IVB); | ||
1385 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1551 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
1386 | } | 1552 | } |
1387 | 1553 | ||
@@ -1562,10 +1728,17 @@ repeat: | |||
1562 | 1728 | ||
1563 | /* drm_dma.h hooks | 1729 | /* drm_dma.h hooks |
1564 | */ | 1730 | */ |
1565 | static void ironlake_irq_preinstall(struct drm_device *dev) | 1731 | void ironlake_irq_preinstall(struct drm_device *dev) |
1566 | { | 1732 | { |
1567 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1733 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1568 | 1734 | ||
1735 | atomic_set(&dev_priv->irq_received, 0); | ||
1736 | |||
1737 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); | ||
1738 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); | ||
1739 | if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) | ||
1740 | INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); | ||
1741 | |||
1569 | I915_WRITE(HWSTAM, 0xeffe); | 1742 | I915_WRITE(HWSTAM, 0xeffe); |
1570 | 1743 | ||
1571 | /* XXX hotplug from PCH */ | 1744 | /* XXX hotplug from PCH */ |
@@ -1585,7 +1758,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev) | |||
1585 | POSTING_READ(SDEIER); | 1758 | POSTING_READ(SDEIER); |
1586 | } | 1759 | } |
1587 | 1760 | ||
1588 | static int ironlake_irq_postinstall(struct drm_device *dev) | 1761 | int ironlake_irq_postinstall(struct drm_device *dev) |
1589 | { | 1762 | { |
1590 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1763 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1591 | /* enable kind of interrupts always enabled */ | 1764 | /* enable kind of interrupts always enabled */ |
@@ -1594,6 +1767,13 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
1594 | u32 render_irqs; | 1767 | u32 render_irqs; |
1595 | u32 hotplug_mask; | 1768 | u32 hotplug_mask; |
1596 | 1769 | ||
1770 | DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); | ||
1771 | if (HAS_BSD(dev)) | ||
1772 | DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); | ||
1773 | if (HAS_BLT(dev)) | ||
1774 | DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); | ||
1775 | |||
1776 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; | ||
1597 | dev_priv->irq_mask = ~display_mask; | 1777 | dev_priv->irq_mask = ~display_mask; |
1598 | 1778 | ||
1599 | /* should always can generate irq */ | 1779 | /* should always can generate irq */ |
@@ -1650,6 +1830,56 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
1650 | return 0; | 1830 | return 0; |
1651 | } | 1831 | } |
1652 | 1832 | ||
1833 | int ivybridge_irq_postinstall(struct drm_device *dev) | ||
1834 | { | ||
1835 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1836 | /* enable kind of interrupts always enabled */ | ||
1837 | u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | | ||
1838 | DE_PCH_EVENT_IVB | DE_PLANEA_FLIP_DONE_IVB | | ||
1839 | DE_PLANEB_FLIP_DONE_IVB; | ||
1840 | u32 render_irqs; | ||
1841 | u32 hotplug_mask; | ||
1842 | |||
1843 | DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); | ||
1844 | if (HAS_BSD(dev)) | ||
1845 | DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); | ||
1846 | if (HAS_BLT(dev)) | ||
1847 | DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); | ||
1848 | |||
1849 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; | ||
1850 | dev_priv->irq_mask = ~display_mask; | ||
1851 | |||
1852 | /* should always can generate irq */ | ||
1853 | I915_WRITE(DEIIR, I915_READ(DEIIR)); | ||
1854 | I915_WRITE(DEIMR, dev_priv->irq_mask); | ||
1855 | I915_WRITE(DEIER, display_mask | DE_PIPEA_VBLANK_IVB | | ||
1856 | DE_PIPEB_VBLANK_IVB); | ||
1857 | POSTING_READ(DEIER); | ||
1858 | |||
1859 | dev_priv->gt_irq_mask = ~0; | ||
1860 | |||
1861 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | ||
1862 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | ||
1863 | |||
1864 | render_irqs = GT_USER_INTERRUPT | GT_GEN6_BSD_USER_INTERRUPT | | ||
1865 | GT_BLT_USER_INTERRUPT; | ||
1866 | I915_WRITE(GTIER, render_irqs); | ||
1867 | POSTING_READ(GTIER); | ||
1868 | |||
1869 | hotplug_mask = (SDE_CRT_HOTPLUG_CPT | | ||
1870 | SDE_PORTB_HOTPLUG_CPT | | ||
1871 | SDE_PORTC_HOTPLUG_CPT | | ||
1872 | SDE_PORTD_HOTPLUG_CPT); | ||
1873 | dev_priv->pch_irq_mask = ~hotplug_mask; | ||
1874 | |||
1875 | I915_WRITE(SDEIIR, I915_READ(SDEIIR)); | ||
1876 | I915_WRITE(SDEIMR, dev_priv->pch_irq_mask); | ||
1877 | I915_WRITE(SDEIER, hotplug_mask); | ||
1878 | POSTING_READ(SDEIER); | ||
1879 | |||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1653 | void i915_driver_irq_preinstall(struct drm_device * dev) | 1883 | void i915_driver_irq_preinstall(struct drm_device * dev) |
1654 | { | 1884 | { |
1655 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1885 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
@@ -1660,11 +1890,6 @@ void i915_driver_irq_preinstall(struct drm_device * dev) | |||
1660 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); | 1890 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); |
1661 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); | 1891 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); |
1662 | 1892 | ||
1663 | if (HAS_PCH_SPLIT(dev)) { | ||
1664 | ironlake_irq_preinstall(dev); | ||
1665 | return; | ||
1666 | } | ||
1667 | |||
1668 | if (I915_HAS_HOTPLUG(dev)) { | 1893 | if (I915_HAS_HOTPLUG(dev)) { |
1669 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 1894 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
1670 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | 1895 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |
@@ -1688,17 +1913,8 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
1688 | u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; | 1913 | u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; |
1689 | u32 error_mask; | 1914 | u32 error_mask; |
1690 | 1915 | ||
1691 | DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); | ||
1692 | if (HAS_BSD(dev)) | ||
1693 | DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); | ||
1694 | if (HAS_BLT(dev)) | ||
1695 | DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); | ||
1696 | |||
1697 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; | 1916 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; |
1698 | 1917 | ||
1699 | if (HAS_PCH_SPLIT(dev)) | ||
1700 | return ironlake_irq_postinstall(dev); | ||
1701 | |||
1702 | /* Unmask the interrupts that we always want on. */ | 1918 | /* Unmask the interrupts that we always want on. */ |
1703 | dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX; | 1919 | dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX; |
1704 | 1920 | ||
@@ -1767,9 +1983,15 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
1767 | return 0; | 1983 | return 0; |
1768 | } | 1984 | } |
1769 | 1985 | ||
1770 | static void ironlake_irq_uninstall(struct drm_device *dev) | 1986 | void ironlake_irq_uninstall(struct drm_device *dev) |
1771 | { | 1987 | { |
1772 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1988 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1989 | |||
1990 | if (!dev_priv) | ||
1991 | return; | ||
1992 | |||
1993 | dev_priv->vblank_pipe = 0; | ||
1994 | |||
1773 | I915_WRITE(HWSTAM, 0xffffffff); | 1995 | I915_WRITE(HWSTAM, 0xffffffff); |
1774 | 1996 | ||
1775 | I915_WRITE(DEIMR, 0xffffffff); | 1997 | I915_WRITE(DEIMR, 0xffffffff); |
@@ -1791,11 +2013,6 @@ void i915_driver_irq_uninstall(struct drm_device * dev) | |||
1791 | 2013 | ||
1792 | dev_priv->vblank_pipe = 0; | 2014 | dev_priv->vblank_pipe = 0; |
1793 | 2015 | ||
1794 | if (HAS_PCH_SPLIT(dev)) { | ||
1795 | ironlake_irq_uninstall(dev); | ||
1796 | return; | ||
1797 | } | ||
1798 | |||
1799 | if (I915_HAS_HOTPLUG(dev)) { | 2016 | if (I915_HAS_HOTPLUG(dev)) { |
1800 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 2017 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
1801 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | 2018 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |