diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 118 |
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 | ||
1462 | static bool i8xx_fbc_enabled(struct drm_device *dev) | 1452 | static 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 | ||