diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-03-28 16:39:38 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-03-28 18:11:22 -0400 |
commit | 7e231dbe0c2a4359472f929732d4200479d8f939 (patch) | |
tree | 1ead8e89c693687c7d39c8cbe44920705b99045a /drivers | |
parent | c46ce4d7e69d129c02640c118f45a86a4412774b (diff) |
drm/i915: ValleyView IRQ support
ValleyView has a new interrupt architecture; best to put it in a new set
of functions. Also make sure the ring mask functions handle ValleyView.
FIXME: fix flipping; need to enable interrupts and call prepare/finish
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 338 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 4 |
4 files changed, 383 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e74674b3097d..d226f2f2f7bc 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -468,7 +468,45 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
468 | if (ret) | 468 | if (ret) |
469 | return ret; | 469 | return ret; |
470 | 470 | ||
471 | if (!HAS_PCH_SPLIT(dev)) { | 471 | if (IS_VALLEYVIEW(dev)) { |
472 | seq_printf(m, "Display IER:\t%08x\n", | ||
473 | I915_READ(VLV_IER)); | ||
474 | seq_printf(m, "Display IIR:\t%08x\n", | ||
475 | I915_READ(VLV_IIR)); | ||
476 | seq_printf(m, "Display IIR_RW:\t%08x\n", | ||
477 | I915_READ(VLV_IIR_RW)); | ||
478 | seq_printf(m, "Display IMR:\t%08x\n", | ||
479 | I915_READ(VLV_IMR)); | ||
480 | for_each_pipe(pipe) | ||
481 | seq_printf(m, "Pipe %c stat:\t%08x\n", | ||
482 | pipe_name(pipe), | ||
483 | I915_READ(PIPESTAT(pipe))); | ||
484 | |||
485 | seq_printf(m, "Master IER:\t%08x\n", | ||
486 | I915_READ(VLV_MASTER_IER)); | ||
487 | |||
488 | seq_printf(m, "Render IER:\t%08x\n", | ||
489 | I915_READ(GTIER)); | ||
490 | seq_printf(m, "Render IIR:\t%08x\n", | ||
491 | I915_READ(GTIIR)); | ||
492 | seq_printf(m, "Render IMR:\t%08x\n", | ||
493 | I915_READ(GTIMR)); | ||
494 | |||
495 | seq_printf(m, "PM IER:\t\t%08x\n", | ||
496 | I915_READ(GEN6_PMIER)); | ||
497 | seq_printf(m, "PM IIR:\t\t%08x\n", | ||
498 | I915_READ(GEN6_PMIIR)); | ||
499 | seq_printf(m, "PM IMR:\t\t%08x\n", | ||
500 | I915_READ(GEN6_PMIMR)); | ||
501 | |||
502 | seq_printf(m, "Port hotplug:\t%08x\n", | ||
503 | I915_READ(PORT_HOTPLUG_EN)); | ||
504 | seq_printf(m, "DPFLIPSTAT:\t%08x\n", | ||
505 | I915_READ(VLV_DPFLIPSTAT)); | ||
506 | seq_printf(m, "DPINVGTT:\t%08x\n", | ||
507 | I915_READ(DPINVGTT)); | ||
508 | |||
509 | } else if (!HAS_PCH_SPLIT(dev)) { | ||
472 | seq_printf(m, "Interrupt enable: %08x\n", | 510 | seq_printf(m, "Interrupt enable: %08x\n", |
473 | I915_READ(IER)); | 511 | I915_READ(IER)); |
474 | seq_printf(m, "Interrupt identity: %08x\n", | 512 | seq_printf(m, "Interrupt identity: %08x\n", |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 998116e871f0..01fb65097977 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -120,6 +120,10 @@ void intel_enable_asle(struct drm_device *dev) | |||
120 | drm_i915_private_t *dev_priv = dev->dev_private; | 120 | drm_i915_private_t *dev_priv = dev->dev_private; |
121 | unsigned long irqflags; | 121 | unsigned long irqflags; |
122 | 122 | ||
123 | /* FIXME: opregion/asle for VLV */ | ||
124 | if (IS_VALLEYVIEW(dev)) | ||
125 | return; | ||
126 | |||
123 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 127 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
124 | 128 | ||
125 | if (HAS_PCH_SPLIT(dev)) | 129 | if (HAS_PCH_SPLIT(dev)) |
@@ -426,6 +430,119 @@ static void gen6_pm_rps_work(struct work_struct *work) | |||
426 | mutex_unlock(&dev_priv->dev->struct_mutex); | 430 | mutex_unlock(&dev_priv->dev->struct_mutex); |
427 | } | 431 | } |
428 | 432 | ||
433 | static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) | ||
434 | { | ||
435 | struct drm_device *dev = (struct drm_device *) arg; | ||
436 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
437 | u32 iir, gt_iir, pm_iir; | ||
438 | irqreturn_t ret = IRQ_NONE; | ||
439 | unsigned long irqflags; | ||
440 | int pipe; | ||
441 | u32 pipe_stats[I915_MAX_PIPES]; | ||
442 | u32 vblank_status; | ||
443 | int vblank = 0; | ||
444 | bool blc_event; | ||
445 | |||
446 | atomic_inc(&dev_priv->irq_received); | ||
447 | |||
448 | vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS | | ||
449 | PIPE_VBLANK_INTERRUPT_STATUS; | ||
450 | |||
451 | while (true) { | ||
452 | iir = I915_READ(VLV_IIR); | ||
453 | gt_iir = I915_READ(GTIIR); | ||
454 | pm_iir = I915_READ(GEN6_PMIIR); | ||
455 | |||
456 | if (gt_iir == 0 && pm_iir == 0 && iir == 0) | ||
457 | goto out; | ||
458 | |||
459 | ret = IRQ_HANDLED; | ||
460 | |||
461 | if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY)) | ||
462 | notify_ring(dev, &dev_priv->ring[RCS]); | ||
463 | if (gt_iir & GT_GEN6_BSD_USER_INTERRUPT) | ||
464 | notify_ring(dev, &dev_priv->ring[VCS]); | ||
465 | if (gt_iir & GT_BLT_USER_INTERRUPT) | ||
466 | notify_ring(dev, &dev_priv->ring[BCS]); | ||
467 | |||
468 | if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT | | ||
469 | GT_GEN6_BSD_CS_ERROR_INTERRUPT | | ||
470 | GT_RENDER_CS_ERROR_INTERRUPT)) { | ||
471 | DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); | ||
472 | i915_handle_error(dev, false); | ||
473 | } | ||
474 | |||
475 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
476 | for_each_pipe(pipe) { | ||
477 | int reg = PIPESTAT(pipe); | ||
478 | pipe_stats[pipe] = I915_READ(reg); | ||
479 | |||
480 | /* | ||
481 | * Clear the PIPE*STAT regs before the IIR | ||
482 | */ | ||
483 | if (pipe_stats[pipe] & 0x8000ffff) { | ||
484 | if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) | ||
485 | DRM_DEBUG_DRIVER("pipe %c underrun\n", | ||
486 | pipe_name(pipe)); | ||
487 | I915_WRITE(reg, pipe_stats[pipe]); | ||
488 | } | ||
489 | } | ||
490 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
491 | |||
492 | /* Consume port. Then clear IIR or we'll miss events */ | ||
493 | if (iir & I915_DISPLAY_PORT_INTERRUPT) { | ||
494 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); | ||
495 | |||
496 | DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", | ||
497 | hotplug_status); | ||
498 | if (hotplug_status & dev_priv->hotplug_supported_mask) | ||
499 | queue_work(dev_priv->wq, | ||
500 | &dev_priv->hotplug_work); | ||
501 | |||
502 | I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); | ||
503 | I915_READ(PORT_HOTPLUG_STAT); | ||
504 | } | ||
505 | |||
506 | |||
507 | if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) { | ||
508 | drm_handle_vblank(dev, 0); | ||
509 | vblank++; | ||
510 | if (!dev_priv->flip_pending_is_done) { | ||
511 | intel_finish_page_flip(dev, 0); | ||
512 | } | ||
513 | } | ||
514 | |||
515 | if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) { | ||
516 | drm_handle_vblank(dev, 1); | ||
517 | vblank++; | ||
518 | if (!dev_priv->flip_pending_is_done) { | ||
519 | intel_finish_page_flip(dev, 0); | ||
520 | } | ||
521 | } | ||
522 | |||
523 | if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) | ||
524 | blc_event = true; | ||
525 | |||
526 | if (pm_iir & GEN6_PM_DEFERRED_EVENTS) { | ||
527 | unsigned long flags; | ||
528 | spin_lock_irqsave(&dev_priv->rps_lock, flags); | ||
529 | WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); | ||
530 | dev_priv->pm_iir |= pm_iir; | ||
531 | I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir); | ||
532 | POSTING_READ(GEN6_PMIMR); | ||
533 | spin_unlock_irqrestore(&dev_priv->rps_lock, flags); | ||
534 | queue_work(dev_priv->wq, &dev_priv->rps_work); | ||
535 | } | ||
536 | |||
537 | I915_WRITE(GTIIR, gt_iir); | ||
538 | I915_WRITE(GEN6_PMIIR, pm_iir); | ||
539 | I915_WRITE(VLV_IIR, iir); | ||
540 | } | ||
541 | |||
542 | out: | ||
543 | return ret; | ||
544 | } | ||
545 | |||
429 | static void pch_irq_handler(struct drm_device *dev) | 546 | static void pch_irq_handler(struct drm_device *dev) |
430 | { | 547 | { |
431 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 548 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
@@ -1567,6 +1684,32 @@ static int ivybridge_enable_vblank(struct drm_device *dev, int pipe) | |||
1567 | return 0; | 1684 | return 0; |
1568 | } | 1685 | } |
1569 | 1686 | ||
1687 | static int valleyview_enable_vblank(struct drm_device *dev, int pipe) | ||
1688 | { | ||
1689 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1690 | unsigned long irqflags; | ||
1691 | u32 dpfl, imr; | ||
1692 | |||
1693 | if (!i915_pipe_enabled(dev, pipe)) | ||
1694 | return -EINVAL; | ||
1695 | |||
1696 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
1697 | dpfl = I915_READ(VLV_DPFLIPSTAT); | ||
1698 | imr = I915_READ(VLV_IMR); | ||
1699 | if (pipe == 0) { | ||
1700 | dpfl |= PIPEA_VBLANK_INT_EN; | ||
1701 | imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; | ||
1702 | } else { | ||
1703 | dpfl |= PIPEA_VBLANK_INT_EN; | ||
1704 | imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | ||
1705 | } | ||
1706 | I915_WRITE(VLV_DPFLIPSTAT, dpfl); | ||
1707 | I915_WRITE(VLV_IMR, imr); | ||
1708 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
1709 | |||
1710 | return 0; | ||
1711 | } | ||
1712 | |||
1570 | /* Called from drm generic code, passed 'crtc' which | 1713 | /* Called from drm generic code, passed 'crtc' which |
1571 | * we use as a pipe index | 1714 | * we use as a pipe index |
1572 | */ | 1715 | */ |
@@ -1608,6 +1751,28 @@ static void ivybridge_disable_vblank(struct drm_device *dev, int pipe) | |||
1608 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1751 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
1609 | } | 1752 | } |
1610 | 1753 | ||
1754 | static void valleyview_disable_vblank(struct drm_device *dev, int pipe) | ||
1755 | { | ||
1756 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1757 | unsigned long irqflags; | ||
1758 | u32 dpfl, imr; | ||
1759 | |||
1760 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
1761 | dpfl = I915_READ(VLV_DPFLIPSTAT); | ||
1762 | imr = I915_READ(VLV_IMR); | ||
1763 | if (pipe == 0) { | ||
1764 | dpfl &= ~PIPEA_VBLANK_INT_EN; | ||
1765 | imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; | ||
1766 | } else { | ||
1767 | dpfl &= ~PIPEB_VBLANK_INT_EN; | ||
1768 | imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | ||
1769 | } | ||
1770 | I915_WRITE(VLV_IMR, imr); | ||
1771 | I915_WRITE(VLV_DPFLIPSTAT, dpfl); | ||
1772 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
1773 | } | ||
1774 | |||
1775 | |||
1611 | /* Set the vblank monitor pipe | 1776 | /* Set the vblank monitor pipe |
1612 | */ | 1777 | */ |
1613 | int i915_vblank_pipe_set(struct drm_device *dev, void *data, | 1778 | int i915_vblank_pipe_set(struct drm_device *dev, void *data, |
@@ -1817,6 +1982,53 @@ static void ironlake_irq_preinstall(struct drm_device *dev) | |||
1817 | POSTING_READ(SDEIER); | 1982 | POSTING_READ(SDEIER); |
1818 | } | 1983 | } |
1819 | 1984 | ||
1985 | static void valleyview_irq_preinstall(struct drm_device *dev) | ||
1986 | { | ||
1987 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1988 | int pipe; | ||
1989 | |||
1990 | atomic_set(&dev_priv->irq_received, 0); | ||
1991 | |||
1992 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); | ||
1993 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); | ||
1994 | |||
1995 | /* VLV magic */ | ||
1996 | I915_WRITE(VLV_IMR, 0); | ||
1997 | I915_WRITE(RING_IMR(RENDER_RING_BASE), 0); | ||
1998 | I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0); | ||
1999 | I915_WRITE(RING_IMR(BLT_RING_BASE), 0); | ||
2000 | |||
2001 | if (IS_GEN6(dev) || IS_GEN7(dev)) { | ||
2002 | /* Workaround stalls observed on Sandy Bridge GPUs by | ||
2003 | * making the blitter command streamer generate a | ||
2004 | * write to the Hardware Status Page for | ||
2005 | * MI_USER_INTERRUPT. This appears to serialize the | ||
2006 | * previous seqno write out before the interrupt | ||
2007 | * happens. | ||
2008 | */ | ||
2009 | I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); | ||
2010 | I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT); | ||
2011 | } | ||
2012 | |||
2013 | /* and GT */ | ||
2014 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | ||
2015 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | ||
2016 | I915_WRITE(GTIMR, 0xffffffff); | ||
2017 | I915_WRITE(GTIER, 0x0); | ||
2018 | POSTING_READ(GTIER); | ||
2019 | |||
2020 | I915_WRITE(DPINVGTT, 0xff); | ||
2021 | |||
2022 | I915_WRITE(PORT_HOTPLUG_EN, 0); | ||
2023 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||
2024 | for_each_pipe(pipe) | ||
2025 | I915_WRITE(PIPESTAT(pipe), 0xffff); | ||
2026 | I915_WRITE(VLV_IIR, 0xffffffff); | ||
2027 | I915_WRITE(VLV_IMR, 0xffffffff); | ||
2028 | I915_WRITE(VLV_IER, 0x0); | ||
2029 | POSTING_READ(VLV_IER); | ||
2030 | } | ||
2031 | |||
1820 | /* | 2032 | /* |
1821 | * Enable digital hotplug on the PCH, and configure the DP short pulse | 2033 | * Enable digital hotplug on the PCH, and configure the DP short pulse |
1822 | * duration to 2ms (which is the minimum in the Display Port spec) | 2034 | * duration to 2ms (which is the minimum in the Display Port spec) |
@@ -1963,6 +2175,96 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) | |||
1963 | return 0; | 2175 | return 0; |
1964 | } | 2176 | } |
1965 | 2177 | ||
2178 | static int valleyview_irq_postinstall(struct drm_device *dev) | ||
2179 | { | ||
2180 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
2181 | u32 render_irqs; | ||
2182 | u32 enable_mask; | ||
2183 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); | ||
2184 | u16 msid; | ||
2185 | |||
2186 | enable_mask = I915_DISPLAY_PORT_INTERRUPT; | ||
2187 | enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | | ||
2188 | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | ||
2189 | |||
2190 | dev_priv->irq_mask = ~enable_mask; | ||
2191 | |||
2192 | |||
2193 | DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); | ||
2194 | DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); | ||
2195 | DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); | ||
2196 | |||
2197 | dev_priv->pipestat[0] = 0; | ||
2198 | dev_priv->pipestat[1] = 0; | ||
2199 | |||
2200 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; | ||
2201 | |||
2202 | /* Hack for broken MSIs on VLV */ | ||
2203 | pci_write_config_dword(dev_priv->dev->pdev, 0x94, 0xfee00000); | ||
2204 | pci_read_config_word(dev->pdev, 0x98, &msid); | ||
2205 | msid &= 0xff; /* mask out delivery bits */ | ||
2206 | msid |= (1<<14); | ||
2207 | pci_write_config_word(dev_priv->dev->pdev, 0x98, msid); | ||
2208 | |||
2209 | I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||
2210 | I915_WRITE(VLV_IER, enable_mask); | ||
2211 | I915_WRITE(VLV_IIR, 0xffffffff); | ||
2212 | I915_WRITE(PIPESTAT(0), 0xffff); | ||
2213 | I915_WRITE(PIPESTAT(1), 0xffff); | ||
2214 | POSTING_READ(VLV_IER); | ||
2215 | |||
2216 | I915_WRITE(VLV_IIR, 0xffffffff); | ||
2217 | I915_WRITE(VLV_IIR, 0xffffffff); | ||
2218 | |||
2219 | render_irqs = GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | | ||
2220 | GT_GEN6_BLT_CS_ERROR_INTERRUPT | | ||
2221 | GT_BLT_USER_INTERRUPT | | ||
2222 | GT_GEN6_BSD_USER_INTERRUPT | | ||
2223 | GT_GEN6_BSD_CS_ERROR_INTERRUPT | | ||
2224 | GT_GEN7_L3_PARITY_ERROR_INTERRUPT | | ||
2225 | GT_PIPE_NOTIFY | | ||
2226 | GT_RENDER_CS_ERROR_INTERRUPT | | ||
2227 | GT_SYNC_STATUS | | ||
2228 | GT_USER_INTERRUPT; | ||
2229 | |||
2230 | dev_priv->gt_irq_mask = ~render_irqs; | ||
2231 | |||
2232 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | ||
2233 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | ||
2234 | I915_WRITE(GTIMR, 0); | ||
2235 | I915_WRITE(GTIER, render_irqs); | ||
2236 | POSTING_READ(GTIER); | ||
2237 | |||
2238 | /* ack & enable invalid PTE error interrupts */ | ||
2239 | #if 0 /* FIXME: add support to irq handler for checking these bits */ | ||
2240 | I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK); | ||
2241 | I915_WRITE(DPINVGTT, DPINVGTT_EN_MASK); | ||
2242 | #endif | ||
2243 | |||
2244 | I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); | ||
2245 | #if 0 /* FIXME: check register definitions; some have moved */ | ||
2246 | /* Note HDMI and DP share bits */ | ||
2247 | if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) | ||
2248 | hotplug_en |= HDMIB_HOTPLUG_INT_EN; | ||
2249 | if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) | ||
2250 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; | ||
2251 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) | ||
2252 | hotplug_en |= HDMID_HOTPLUG_INT_EN; | ||
2253 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) | ||
2254 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | ||
2255 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) | ||
2256 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | ||
2257 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { | ||
2258 | hotplug_en |= CRT_HOTPLUG_INT_EN; | ||
2259 | hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; | ||
2260 | } | ||
2261 | #endif | ||
2262 | |||
2263 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); | ||
2264 | |||
2265 | return 0; | ||
2266 | } | ||
2267 | |||
1966 | static void i915_driver_irq_preinstall(struct drm_device * dev) | 2268 | static void i915_driver_irq_preinstall(struct drm_device * dev) |
1967 | { | 2269 | { |
1968 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 2270 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
@@ -2066,6 +2368,30 @@ static int i915_driver_irq_postinstall(struct drm_device *dev) | |||
2066 | return 0; | 2368 | return 0; |
2067 | } | 2369 | } |
2068 | 2370 | ||
2371 | static void valleyview_irq_uninstall(struct drm_device *dev) | ||
2372 | { | ||
2373 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
2374 | int pipe; | ||
2375 | |||
2376 | if (!dev_priv) | ||
2377 | return; | ||
2378 | |||
2379 | dev_priv->vblank_pipe = 0; | ||
2380 | |||
2381 | for_each_pipe(pipe) | ||
2382 | I915_WRITE(PIPESTAT(pipe), 0xffff); | ||
2383 | |||
2384 | I915_WRITE(HWSTAM, 0xffffffff); | ||
2385 | I915_WRITE(PORT_HOTPLUG_EN, 0); | ||
2386 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||
2387 | for_each_pipe(pipe) | ||
2388 | I915_WRITE(PIPESTAT(pipe), 0xffff); | ||
2389 | I915_WRITE(VLV_IIR, 0xffffffff); | ||
2390 | I915_WRITE(VLV_IMR, 0xffffffff); | ||
2391 | I915_WRITE(VLV_IER, 0x0); | ||
2392 | POSTING_READ(VLV_IER); | ||
2393 | } | ||
2394 | |||
2069 | static void ironlake_irq_uninstall(struct drm_device *dev) | 2395 | static void ironlake_irq_uninstall(struct drm_device *dev) |
2070 | { | 2396 | { |
2071 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 2397 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
@@ -2121,7 +2447,8 @@ void intel_irq_init(struct drm_device *dev) | |||
2121 | { | 2447 | { |
2122 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | 2448 | dev->driver->get_vblank_counter = i915_get_vblank_counter; |
2123 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | 2449 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
2124 | if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { | 2450 | if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev) || |
2451 | IS_VALLEYVIEW(dev)) { | ||
2125 | dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ | 2452 | dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ |
2126 | dev->driver->get_vblank_counter = gm45_get_vblank_counter; | 2453 | dev->driver->get_vblank_counter = gm45_get_vblank_counter; |
2127 | } | 2454 | } |
@@ -2132,7 +2459,14 @@ void intel_irq_init(struct drm_device *dev) | |||
2132 | dev->driver->get_vblank_timestamp = NULL; | 2459 | dev->driver->get_vblank_timestamp = NULL; |
2133 | dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; | 2460 | dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; |
2134 | 2461 | ||
2135 | if (IS_IVYBRIDGE(dev)) { | 2462 | if (IS_VALLEYVIEW(dev)) { |
2463 | dev->driver->irq_handler = valleyview_irq_handler; | ||
2464 | dev->driver->irq_preinstall = valleyview_irq_preinstall; | ||
2465 | dev->driver->irq_postinstall = valleyview_irq_postinstall; | ||
2466 | dev->driver->irq_uninstall = valleyview_irq_uninstall; | ||
2467 | dev->driver->enable_vblank = valleyview_enable_vblank; | ||
2468 | dev->driver->disable_vblank = valleyview_disable_vblank; | ||
2469 | } else if (IS_IVYBRIDGE(dev)) { | ||
2136 | /* Share pre & uninstall handlers with ILK/SNB */ | 2470 | /* Share pre & uninstall handlers with ILK/SNB */ |
2137 | dev->driver->irq_handler = ivybridge_irq_handler; | 2471 | dev->driver->irq_handler = ivybridge_irq_handler; |
2138 | dev->driver->irq_preinstall = ironlake_irq_preinstall; | 2472 | dev->driver->irq_preinstall = ironlake_irq_preinstall; |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0bcad74de7be..908550c72a0d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -510,6 +510,11 @@ | |||
510 | #define IIR 0x020a4 | 510 | #define IIR 0x020a4 |
511 | #define IMR 0x020a8 | 511 | #define IMR 0x020a8 |
512 | #define ISR 0x020ac | 512 | #define ISR 0x020ac |
513 | #define VLV_IIR_RW 0x182084 | ||
514 | #define VLV_IER 0x1820a0 | ||
515 | #define VLV_IIR 0x1820a4 | ||
516 | #define VLV_IMR 0x1820a8 | ||
517 | #define VLV_ISR 0x1820ac | ||
513 | #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) | 518 | #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) |
514 | #define I915_DISPLAY_PORT_INTERRUPT (1<<17) | 519 | #define I915_DISPLAY_PORT_INTERRUPT (1<<17) |
515 | #define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) | 520 | #define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) |
@@ -2533,7 +2538,7 @@ | |||
2533 | #define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL) | 2538 | #define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL) |
2534 | #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) | 2539 | #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) |
2535 | 2540 | ||
2536 | #define DPFLIPSTAT_VLV 0x70028 | 2541 | #define VLV_DPFLIPSTAT 0x70028 |
2537 | #define PIPEB_LINE_COMPARE_STATUS (1<<29) | 2542 | #define PIPEB_LINE_COMPARE_STATUS (1<<29) |
2538 | #define PIPEB_HLINE_INT_EN (1<<28) | 2543 | #define PIPEB_HLINE_INT_EN (1<<28) |
2539 | #define PIPEB_VBLANK_INT_EN (1<<27) | 2544 | #define PIPEB_VBLANK_INT_EN (1<<27) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b7b50a5b0478..75081f146390 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -687,7 +687,7 @@ render_ring_get_irq(struct intel_ring_buffer *ring) | |||
687 | 687 | ||
688 | spin_lock(&ring->irq_lock); | 688 | spin_lock(&ring->irq_lock); |
689 | if (ring->irq_refcount++ == 0) { | 689 | if (ring->irq_refcount++ == 0) { |
690 | if (HAS_PCH_SPLIT(dev)) | 690 | if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev)) |
691 | ironlake_enable_irq(dev_priv, | 691 | ironlake_enable_irq(dev_priv, |
692 | GT_PIPE_NOTIFY | GT_USER_INTERRUPT); | 692 | GT_PIPE_NOTIFY | GT_USER_INTERRUPT); |
693 | else | 693 | else |
@@ -706,7 +706,7 @@ render_ring_put_irq(struct intel_ring_buffer *ring) | |||
706 | 706 | ||
707 | spin_lock(&ring->irq_lock); | 707 | spin_lock(&ring->irq_lock); |
708 | if (--ring->irq_refcount == 0) { | 708 | if (--ring->irq_refcount == 0) { |
709 | if (HAS_PCH_SPLIT(dev)) | 709 | if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev)) |
710 | ironlake_disable_irq(dev_priv, | 710 | ironlake_disable_irq(dev_priv, |
711 | GT_USER_INTERRUPT | | 711 | GT_USER_INTERRUPT | |
712 | GT_PIPE_NOTIFY); | 712 | GT_PIPE_NOTIFY); |