aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-09-21 00:48:45 -0400
committerDave Airlie <airlied@redhat.com>2009-09-21 00:48:45 -0400
commitaadd4e17452d3d5c2269cd2b000b7de7cfb6c79e (patch)
tree7db901a331809805874891319e0624c055a08662
parent5a6e9f9658c853fea8ebbf64cd36287f00a011a2 (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>
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c23
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h3
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 fa063d0cfb6..4f7afc79dd8 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 */
654static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) 666static 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 bc79ad6199b..cb0cfe4b308 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)