aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
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