aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-07-08 07:22:43 -0400
committerKeith Packard <keithp@keithp.com>2011-07-08 13:23:20 -0400
commit016b9b61ed692498a5d46dff974fe41b20e7e60b (patch)
treeb36de4779e9609c262696fe43c1cae8bc55501d9 /drivers
parent1630fe754c83b3e57efa51c85f1a21e612a63a0e (diff)
drm/i915: Share the common work of disabling active FBC before updating
Upon review, all path share the same dependencies for updating the registers and so we can benefit from sharing the code and checking early. This removes the unsightly intel_wait_for_vblank() from the lowlevel functions and upon further analysis the only path that will require a wait is if we are performing an instantaneous transition between two valid FBC configurations. The page-flip path itself will have disabled FBC registers and will have waited for at least one vblank before finishing the flip and attempting to re-enable FBC. This wait can be accomplished simply by delaying the enable until after we are sure that a vblank will have passed, which we are already doing to make sure that the display is settled before enabling FBC. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h6
-rw-r--r--drivers/gpu/drm/i915/intel_display.c118
2 files changed, 64 insertions, 60 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3154b3dfd804..00dc59a51ccd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -331,10 +331,8 @@ typedef struct drm_i915_private {
331 uint32_t last_instdone1; 331 uint32_t last_instdone1;
332 332
333 unsigned long cfb_size; 333 unsigned long cfb_size;
334 unsigned long cfb_pitch; 334 unsigned int cfb_fb;
335 unsigned long cfb_offset; 335 enum plane cfb_plane;
336 int cfb_fence;
337 int cfb_plane;
338 int cfb_y; 336 int cfb_y;
339 struct intel_fbc_work *fbc_work; 337 struct intel_fbc_work *fbc_work;
340 338
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index df2839c59b74..b5b15bda71d9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1414,27 +1414,17 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1414 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 1414 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
1415 struct drm_i915_gem_object *obj = intel_fb->obj; 1415 struct drm_i915_gem_object *obj = intel_fb->obj;
1416 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 1416 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1417 int cfb_pitch;
1417 int plane, i; 1418 int plane, i;
1418 u32 fbc_ctl, fbc_ctl2; 1419 u32 fbc_ctl, fbc_ctl2;
1419 1420
1420 if (fb->pitch == dev_priv->cfb_pitch && 1421 cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
1421 obj->fence_reg == dev_priv->cfb_fence && 1422 if (fb->pitch < cfb_pitch)
1422 intel_crtc->plane == dev_priv->cfb_plane && 1423 cfb_pitch = fb->pitch;
1423 I915_READ(FBC_CONTROL) & FBC_CTL_EN)
1424 return;
1425
1426 i8xx_disable_fbc(dev);
1427
1428 dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
1429
1430 if (fb->pitch < dev_priv->cfb_pitch)
1431 dev_priv->cfb_pitch = fb->pitch;
1432 1424
1433 /* FBC_CTL wants 64B units */ 1425 /* FBC_CTL wants 64B units */
1434 dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; 1426 cfb_pitch = (cfb_pitch / 64) - 1;
1435 dev_priv->cfb_fence = obj->fence_reg; 1427 plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
1436 dev_priv->cfb_plane = intel_crtc->plane;
1437 plane = dev_priv->cfb_plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
1438 1428
1439 /* Clear old tags */ 1429 /* Clear old tags */
1440 for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) 1430 for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
@@ -1450,13 +1440,13 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1450 fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; 1440 fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
1451 if (IS_I945GM(dev)) 1441 if (IS_I945GM(dev))
1452 fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ 1442 fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
1453 fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; 1443 fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
1454 fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; 1444 fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
1455 fbc_ctl |= dev_priv->cfb_fence; 1445 fbc_ctl |= obj->fence_reg;
1456 I915_WRITE(FBC_CONTROL, fbc_ctl); 1446 I915_WRITE(FBC_CONTROL, fbc_ctl);
1457 1447
1458 DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ", 1448 DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ",
1459 dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); 1449 cfb_pitch, crtc->y, intel_crtc->plane);
1460} 1450}
1461 1451
1462static bool i8xx_fbc_enabled(struct drm_device *dev) 1452static bool i8xx_fbc_enabled(struct drm_device *dev)
@@ -1478,23 +1468,8 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1478 unsigned long stall_watermark = 200; 1468 unsigned long stall_watermark = 200;
1479 u32 dpfc_ctl; 1469 u32 dpfc_ctl;
1480 1470
1481 dpfc_ctl = I915_READ(DPFC_CONTROL);
1482 if (dpfc_ctl & DPFC_CTL_EN) {
1483 if (dev_priv->cfb_fence == obj->fence_reg &&
1484 dev_priv->cfb_plane == intel_crtc->plane &&
1485 dev_priv->cfb_y == crtc->y)
1486 return;
1487
1488 I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
1489 intel_wait_for_vblank(dev, intel_crtc->pipe);
1490 }
1491
1492 dev_priv->cfb_fence = obj->fence_reg;
1493 dev_priv->cfb_plane = intel_crtc->plane;
1494 dev_priv->cfb_y = crtc->y;
1495
1496 dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; 1471 dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
1497 dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence; 1472 dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
1498 I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); 1473 I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
1499 1474
1500 I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | 1475 I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
@@ -1563,27 +1538,11 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1563 u32 dpfc_ctl; 1538 u32 dpfc_ctl;
1564 1539
1565 dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); 1540 dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
1566 if (dpfc_ctl & DPFC_CTL_EN) {
1567 if (dev_priv->cfb_fence == obj->fence_reg &&
1568 dev_priv->cfb_plane == intel_crtc->plane &&
1569 dev_priv->cfb_offset == obj->gtt_offset &&
1570 dev_priv->cfb_y == crtc->y)
1571 return;
1572
1573 I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
1574 intel_wait_for_vblank(dev, intel_crtc->pipe);
1575 }
1576
1577 dev_priv->cfb_fence = obj->fence_reg;
1578 dev_priv->cfb_plane = intel_crtc->plane;
1579 dev_priv->cfb_offset = obj->gtt_offset;
1580 dev_priv->cfb_y = crtc->y;
1581
1582 dpfc_ctl &= DPFC_RESERVED; 1541 dpfc_ctl &= DPFC_RESERVED;
1583 dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); 1542 dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
1584 /* Set persistent mode for front-buffer rendering, ala X. */ 1543 /* Set persistent mode for front-buffer rendering, ala X. */
1585 dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE; 1544 dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
1586 dpfc_ctl |= (DPFC_CTL_FENCE_EN | dev_priv->cfb_fence); 1545 dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg);
1587 I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); 1546 I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
1588 1547
1589 I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | 1548 I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
@@ -1596,7 +1555,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1596 1555
1597 if (IS_GEN6(dev)) { 1556 if (IS_GEN6(dev)) {
1598 I915_WRITE(SNB_DPFC_CTL_SA, 1557 I915_WRITE(SNB_DPFC_CTL_SA,
1599 SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence); 1558 SNB_CPU_FENCE_ENABLE | obj->fence_reg);
1600 I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); 1559 I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
1601 sandybridge_blit_fbc_update(dev); 1560 sandybridge_blit_fbc_update(dev);
1602 } 1561 }
@@ -1649,10 +1608,15 @@ static void intel_fbc_work_fn(struct work_struct *__work)
1649 /* Double check that we haven't switched fb without cancelling 1608 /* Double check that we haven't switched fb without cancelling
1650 * the prior work. 1609 * the prior work.
1651 */ 1610 */
1652 if (work->crtc->fb == work->fb) 1611 if (work->crtc->fb == work->fb) {
1653 dev_priv->display.enable_fbc(work->crtc, 1612 dev_priv->display.enable_fbc(work->crtc,
1654 work->interval); 1613 work->interval);
1655 1614
1615 dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane;
1616 dev_priv->cfb_fb = work->crtc->fb->base.id;
1617 dev_priv->cfb_y = work->crtc->y;
1618 }
1619
1656 dev_priv->fbc_work = NULL; 1620 dev_priv->fbc_work = NULL;
1657 } 1621 }
1658 mutex_unlock(&dev->struct_mutex); 1622 mutex_unlock(&dev->struct_mutex);
@@ -1710,7 +1674,10 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1710 DRM_DEBUG_KMS("scheduling delayed FBC enable\n"); 1674 DRM_DEBUG_KMS("scheduling delayed FBC enable\n");
1711 1675
1712 /* Delay the actual enabling to let pageflipping cease and the 1676 /* Delay the actual enabling to let pageflipping cease and the
1713 * display to settle before starting the compression. 1677 * display to settle before starting the compression. Note that
1678 * this delay also serves a second purpose: it allows for a
1679 * vblank to pass after disabling the FBC before we attempt
1680 * to modify the control registers.
1714 * 1681 *
1715 * A more complicated solution would involve tracking vblanks 1682 * A more complicated solution would involve tracking vblanks
1716 * following the termination of the page-flipping sequence 1683 * following the termination of the page-flipping sequence
@@ -1730,6 +1697,7 @@ void intel_disable_fbc(struct drm_device *dev)
1730 return; 1697 return;
1731 1698
1732 dev_priv->display.disable_fbc(dev); 1699 dev_priv->display.disable_fbc(dev);
1700 dev_priv->cfb_plane = -1;
1733} 1701}
1734 1702
1735/** 1703/**
@@ -1843,6 +1811,44 @@ static void intel_update_fbc(struct drm_device *dev)
1843 if (in_dbg_master()) 1811 if (in_dbg_master())
1844 goto out_disable; 1812 goto out_disable;
1845 1813
1814 /* If the scanout has not changed, don't modify the FBC settings.
1815 * Note that we make the fundamental assumption that the fb->obj
1816 * cannot be unpinned (and have its GTT offset and fence revoked)
1817 * without first being decoupled from the scanout and FBC disabled.
1818 */
1819 if (dev_priv->cfb_plane == intel_crtc->plane &&
1820 dev_priv->cfb_fb == fb->base.id &&
1821 dev_priv->cfb_y == crtc->y)
1822 return;
1823
1824 if (intel_fbc_enabled(dev)) {
1825 /* We update FBC along two paths, after changing fb/crtc
1826 * configuration (modeswitching) and after page-flipping
1827 * finishes. For the latter, we know that not only did
1828 * we disable the FBC at the start of the page-flip
1829 * sequence, but also more than one vblank has passed.
1830 *
1831 * For the former case of modeswitching, it is possible
1832 * to switch between two FBC valid configurations
1833 * instantaneously so we do need to disable the FBC
1834 * before we can modify its control registers. We also
1835 * have to wait for the next vblank for that to take
1836 * effect. However, since we delay enabling FBC we can
1837 * assume that a vblank has passed since disabling and
1838 * that we can safely alter the registers in the deferred
1839 * callback.
1840 *
1841 * In the scenario that we go from a valid to invalid
1842 * and then back to valid FBC configuration we have
1843 * no strict enforcement that a vblank occurred since
1844 * disabling the FBC. However, along all current pipe
1845 * disabling paths we do need to wait for a vblank at
1846 * some point. And we wait before enabling FBC anyway.
1847 */
1848 DRM_DEBUG_KMS("disabling active FBC for update\n");
1849 intel_disable_fbc(dev);
1850 }
1851
1846 intel_enable_fbc(crtc, 500); 1852 intel_enable_fbc(crtc, 500);
1847 return; 1853 return;
1848 1854