diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-04-10 09:58:42 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-04-22 10:39:08 -0400 |
commit | 968c01664ccbe0e46c19a1af662c4c266a904203 (patch) | |
tree | 886a1c76b96d967c525a3a31dded04e67bd651ba /drivers/gpu/drm/radeon/evergreen.c | |
parent | 2f86e2ede39a98650c2d465857405ef1c51372b1 (diff) |
drm/radeon: properly lock disp in mc_stop/resume for evergreen+
Need to wait for the new addresses to take affect before
re-enabling the MC.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index f8a5b6063496..42111e6b5282 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1575,18 +1575,14 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav | |||
1575 | if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { | 1575 | if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { |
1576 | radeon_wait_for_vblank(rdev, i); | 1576 | radeon_wait_for_vblank(rdev, i); |
1577 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; | 1577 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; |
1578 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); | ||
1579 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); | 1578 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); |
1580 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); | ||
1581 | } | 1579 | } |
1582 | } else { | 1580 | } else { |
1583 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); | 1581 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); |
1584 | if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { | 1582 | if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { |
1585 | radeon_wait_for_vblank(rdev, i); | 1583 | radeon_wait_for_vblank(rdev, i); |
1586 | tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; | 1584 | tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; |
1587 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); | ||
1588 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); | 1585 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); |
1589 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); | ||
1590 | } | 1586 | } |
1591 | } | 1587 | } |
1592 | /* wait for the next frame */ | 1588 | /* wait for the next frame */ |
@@ -1613,6 +1609,22 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav | |||
1613 | } | 1609 | } |
1614 | /* wait for the MC to settle */ | 1610 | /* wait for the MC to settle */ |
1615 | udelay(100); | 1611 | udelay(100); |
1612 | |||
1613 | /* lock double buffered regs */ | ||
1614 | for (i = 0; i < rdev->num_crtc; i++) { | ||
1615 | if (save->crtc_enabled[i]) { | ||
1616 | tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); | ||
1617 | if (!(tmp & EVERGREEN_GRPH_UPDATE_LOCK)) { | ||
1618 | tmp |= EVERGREEN_GRPH_UPDATE_LOCK; | ||
1619 | WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp); | ||
1620 | } | ||
1621 | tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]); | ||
1622 | if (!(tmp & 1)) { | ||
1623 | tmp |= 1; | ||
1624 | WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp); | ||
1625 | } | ||
1626 | } | ||
1627 | } | ||
1616 | } | 1628 | } |
1617 | 1629 | ||
1618 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) | 1630 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) |
@@ -1634,6 +1646,33 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s | |||
1634 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); | 1646 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); |
1635 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); | 1647 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); |
1636 | 1648 | ||
1649 | /* unlock regs and wait for update */ | ||
1650 | for (i = 0; i < rdev->num_crtc; i++) { | ||
1651 | if (save->crtc_enabled[i]) { | ||
1652 | tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]); | ||
1653 | if ((tmp & 0x3) != 0) { | ||
1654 | tmp &= ~0x3; | ||
1655 | WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp); | ||
1656 | } | ||
1657 | tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); | ||
1658 | if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) { | ||
1659 | tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; | ||
1660 | WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp); | ||
1661 | } | ||
1662 | tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]); | ||
1663 | if (tmp & 1) { | ||
1664 | tmp &= ~1; | ||
1665 | WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp); | ||
1666 | } | ||
1667 | for (j = 0; j < rdev->usec_timeout; j++) { | ||
1668 | tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); | ||
1669 | if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0) | ||
1670 | break; | ||
1671 | udelay(1); | ||
1672 | } | ||
1673 | } | ||
1674 | } | ||
1675 | |||
1637 | /* unblackout the MC */ | 1676 | /* unblackout the MC */ |
1638 | tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); | 1677 | tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); |
1639 | tmp &= ~BLACKOUT_MODE_MASK; | 1678 | tmp &= ~BLACKOUT_MODE_MASK; |