aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2014-04-29 06:35:46 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-05-06 04:18:02 -0400
commit8d7849db3eab7f560deba145dfed3cd4df97c975 (patch)
tree8c953720cdf774cfff43d5b79c3994be444df8b7 /drivers/gpu/drm/i915/i915_irq.c
parentd9ceb957fd97836c7fb0e403062e68ad2f737021 (diff)
drm/i915: Make sprite updates atomic
Add a mechanism by which we can evade the leading edge of vblank. This guarantees that no two sprite register writes will straddle on either side of the vblank start, and that means all the writes will be latched together in one atomic operation. We do the vblank evade by checking the scanline counter, and if it's too close to the start of vblank (too close has been hardcoded to 100usec for now), we will wait for the vblank start to pass. In order to eliminate random delayes from the rest of the system, we operate with interrupts disabled, except when waiting for the vblank obviously. Note that we now go digging through pipe_to_crtc_mapping[] in the vblank interrupt handler, which is a bit dangerous since we set up interrupts before the crtcs. However in this case since it's the vblank interrupt, we don't actually unmask it until some piece of code requests it. v2: preempt_check_resched() calls after local_irq_enable() (Jesse) Hook up the vblank irq stuff on BDW as well v3: Pass intel_crtc instead of drm_crtc (Daniel) Warn if crtc.mutex isn't locked (Daniel) Add an explicit compiler barrier and document the barriers (Daniel) Note the irq vs. modeset setup madness in the commit message (Daniel) v4: Use prepare_to_wait() & co. directly and eliminate vbl_received v5: Refactor intel_pipe_handle_vblank() vs. drm_handle_vblank() (Chris) Check for min/max scanline <= 0 (Chris) Don't call intel_pipe_update_end() if start failed totally (Chris) Check that the vblank counters match on both sides of the critical section (Chris) v6: Fix atomic update for interlaced modes v7: Reorder code for better readability (Chris) v8: Drop preempt_check_resched(). It's not available to modules anymore and isn't even needed unless we ourselves cause a wakeup needing reschedule while interrupts are off Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Reviewed-by: Sourab Gupta <sourabgupta@gmail.com> Reviewed-by: Akash Goel <akash.goels@gmail.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 1e60f24736da..2d7618366b75 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1556,6 +1556,19 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
1556 } 1556 }
1557} 1557}
1558 1558
1559static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe)
1560{
1561 struct intel_crtc *crtc;
1562
1563 if (!drm_handle_vblank(dev, pipe))
1564 return false;
1565
1566 crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
1567 wake_up(&crtc->vbl_wait);
1568
1569 return true;
1570}
1571
1559static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) 1572static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
1560{ 1573{
1561 struct drm_i915_private *dev_priv = dev->dev_private; 1574 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1607,7 +1620,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
1607 1620
1608 for_each_pipe(pipe) { 1621 for_each_pipe(pipe) {
1609 if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1622 if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
1610 drm_handle_vblank(dev, pipe); 1623 intel_pipe_handle_vblank(dev, pipe);
1611 1624
1612 if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) { 1625 if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) {
1613 intel_prepare_page_flip(dev, pipe); 1626 intel_prepare_page_flip(dev, pipe);
@@ -1850,7 +1863,7 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
1850 1863
1851 for_each_pipe(pipe) { 1864 for_each_pipe(pipe) {
1852 if (de_iir & DE_PIPE_VBLANK(pipe)) 1865 if (de_iir & DE_PIPE_VBLANK(pipe))
1853 drm_handle_vblank(dev, pipe); 1866 intel_pipe_handle_vblank(dev, pipe);
1854 1867
1855 if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 1868 if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
1856 if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) 1869 if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
@@ -1900,7 +1913,7 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
1900 1913
1901 for_each_pipe(pipe) { 1914 for_each_pipe(pipe) {
1902 if (de_iir & (DE_PIPE_VBLANK_IVB(pipe))) 1915 if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)))
1903 drm_handle_vblank(dev, pipe); 1916 intel_pipe_handle_vblank(dev, pipe);
1904 1917
1905 /* plane/pipes map 1:1 on ilk+ */ 1918 /* plane/pipes map 1:1 on ilk+ */
1906 if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) { 1919 if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) {
@@ -2043,7 +2056,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
2043 2056
2044 pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); 2057 pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
2045 if (pipe_iir & GEN8_PIPE_VBLANK) 2058 if (pipe_iir & GEN8_PIPE_VBLANK)
2046 drm_handle_vblank(dev, pipe); 2059 intel_pipe_handle_vblank(dev, pipe);
2047 2060
2048 if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) { 2061 if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
2049 intel_prepare_page_flip(dev, pipe); 2062 intel_prepare_page_flip(dev, pipe);
@@ -3390,7 +3403,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
3390 struct drm_i915_private *dev_priv = dev->dev_private; 3403 struct drm_i915_private *dev_priv = dev->dev_private;
3391 u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane); 3404 u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
3392 3405
3393 if (!drm_handle_vblank(dev, pipe)) 3406 if (!intel_pipe_handle_vblank(dev, pipe))
3394 return false; 3407 return false;
3395 3408
3396 if ((iir & flip_pending) == 0) 3409 if ((iir & flip_pending) == 0)
@@ -3575,7 +3588,7 @@ static bool i915_handle_vblank(struct drm_device *dev,
3575 struct drm_i915_private *dev_priv = dev->dev_private; 3588 struct drm_i915_private *dev_priv = dev->dev_private;
3576 u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane); 3589 u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
3577 3590
3578 if (!drm_handle_vblank(dev, pipe)) 3591 if (!intel_pipe_handle_vblank(dev, pipe))
3579 return false; 3592 return false;
3580 3593
3581 if ((iir & flip_pending) == 0) 3594 if ((iir & flip_pending) == 0)