diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-09-21 00:48:45 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-09-21 00:48:45 -0400 |
commit | aadd4e17452d3d5c2269cd2b000b7de7cfb6c79e (patch) | |
tree | 7db901a331809805874891319e0624c055a08662 /drivers | |
parent | 5a6e9f9658c853fea8ebbf64cd36287f00a011a2 (diff) |
drm/radeon: some r420s have a CP race with the DMA engine.
This patch makes sure the CP doesn't DMA do VRAM while 2D
is active by inserting a CP resync token.
todo: port to kms.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_cp.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.h | 3 |
2 files changed, 26 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index fa063d0cfb63..4f7afc79dd82 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
@@ -616,6 +616,18 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) | |||
616 | 616 | ||
617 | dev_priv->cp_running = 1; | 617 | dev_priv->cp_running = 1; |
618 | 618 | ||
619 | /* on r420, any DMA from CP to system memory while 2D is active | ||
620 | * can cause a hang. workaround is to queue a CP RESYNC token | ||
621 | */ | ||
622 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) { | ||
623 | BEGIN_RING(3); | ||
624 | OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1)); | ||
625 | OUT_RING(5); /* scratch reg 5 */ | ||
626 | OUT_RING(0xdeadbeef); | ||
627 | ADVANCE_RING(); | ||
628 | COMMIT_RING(); | ||
629 | } | ||
630 | |||
619 | BEGIN_RING(8); | 631 | BEGIN_RING(8); |
620 | /* isync can only be written through cp on r5xx write it here */ | 632 | /* isync can only be written through cp on r5xx write it here */ |
621 | OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); | 633 | OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); |
@@ -653,8 +665,19 @@ static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv) | |||
653 | */ | 665 | */ |
654 | static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) | 666 | static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) |
655 | { | 667 | { |
668 | RING_LOCALS; | ||
656 | DRM_DEBUG("\n"); | 669 | DRM_DEBUG("\n"); |
657 | 670 | ||
671 | /* finish the pending CP_RESYNC token */ | ||
672 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) { | ||
673 | BEGIN_RING(2); | ||
674 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
675 | OUT_RING(R300_RB3D_DC_FINISH); | ||
676 | ADVANCE_RING(); | ||
677 | COMMIT_RING(); | ||
678 | radeon_do_wait_for_idle(dev_priv); | ||
679 | } | ||
680 | |||
658 | RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS); | 681 | RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS); |
659 | 682 | ||
660 | dev_priv->cp_running = 0; | 683 | dev_priv->cp_running = 0; |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index bc79ad6199bc..cb0cfe4b3082 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h | |||
@@ -1099,6 +1099,9 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index); | |||
1099 | # define RADEON_CSQ_PRIBM_INDBM (4 << 28) | 1099 | # define RADEON_CSQ_PRIBM_INDBM (4 << 28) |
1100 | # define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) | 1100 | # define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) |
1101 | 1101 | ||
1102 | #define R300_CP_RESYNC_ADDR 0x0778 | ||
1103 | #define R300_CP_RESYNC_DATA 0x077c | ||
1104 | |||
1102 | #define RADEON_AIC_CNTL 0x01d0 | 1105 | #define RADEON_AIC_CNTL 0x01d0 |
1103 | # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) | 1106 | # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) |
1104 | # define RS400_MSI_REARM (1 << 3) | 1107 | # define RS400_MSI_REARM (1 << 3) |