diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r300_cmdbuf.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r300_cmdbuf.c | 117 |
1 files changed, 97 insertions, 20 deletions
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 702df45320f7..4b3bd6303daf 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c | |||
@@ -136,6 +136,18 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, | |||
136 | ADVANCE_RING(); | 136 | ADVANCE_RING(); |
137 | } | 137 | } |
138 | 138 | ||
139 | /* flus cache and wait idle clean after cliprect change */ | ||
140 | BEGIN_RING(2); | ||
141 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
142 | OUT_RING(R300_RB3D_DC_FLUSH); | ||
143 | ADVANCE_RING(); | ||
144 | BEGIN_RING(2); | ||
145 | OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
146 | OUT_RING(RADEON_WAIT_3D_IDLECLEAN); | ||
147 | ADVANCE_RING(); | ||
148 | /* set flush flag */ | ||
149 | dev_priv->track_flush |= RADEON_FLUSH_EMITED; | ||
150 | |||
139 | return 0; | 151 | return 0; |
140 | } | 152 | } |
141 | 153 | ||
@@ -166,13 +178,13 @@ void r300_init_reg_flags(struct drm_device *dev) | |||
166 | ADD_RANGE(0x21DC, 1); | 178 | ADD_RANGE(0x21DC, 1); |
167 | ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); | 179 | ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); |
168 | ADD_RANGE(R300_VAP_CLIP_X_0, 4); | 180 | ADD_RANGE(R300_VAP_CLIP_X_0, 4); |
169 | ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1); | 181 | ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1); |
170 | ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); | 182 | ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); |
171 | ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); | 183 | ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); |
172 | ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); | 184 | ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); |
173 | ADD_RANGE(R300_GB_ENABLE, 1); | 185 | ADD_RANGE(R300_GB_ENABLE, 1); |
174 | ADD_RANGE(R300_GB_MSPOS0, 5); | 186 | ADD_RANGE(R300_GB_MSPOS0, 5); |
175 | ADD_RANGE(R300_TX_CNTL, 1); | 187 | ADD_RANGE(R300_TX_INVALTAGS, 1); |
176 | ADD_RANGE(R300_TX_ENABLE, 1); | 188 | ADD_RANGE(R300_TX_ENABLE, 1); |
177 | ADD_RANGE(0x4200, 4); | 189 | ADD_RANGE(0x4200, 4); |
178 | ADD_RANGE(0x4214, 1); | 190 | ADD_RANGE(0x4214, 1); |
@@ -388,15 +400,28 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, | |||
388 | if (sz * 16 > cmdbuf->bufsz) | 400 | if (sz * 16 > cmdbuf->bufsz) |
389 | return -EINVAL; | 401 | return -EINVAL; |
390 | 402 | ||
391 | BEGIN_RING(5 + sz * 4); | 403 | /* VAP is very sensitive so we purge cache before we program it |
392 | /* Wait for VAP to come to senses.. */ | 404 | * and we also flush its state before & after */ |
393 | /* there is no need to emit it multiple times, (only once before VAP is programmed, | 405 | BEGIN_RING(6); |
394 | but this optimization is for later */ | 406 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); |
395 | OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0); | 407 | OUT_RING(R300_RB3D_DC_FLUSH); |
408 | OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
409 | OUT_RING(RADEON_WAIT_3D_IDLECLEAN); | ||
410 | OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); | ||
411 | OUT_RING(0); | ||
412 | ADVANCE_RING(); | ||
413 | /* set flush flag */ | ||
414 | dev_priv->track_flush |= RADEON_FLUSH_EMITED; | ||
415 | |||
416 | BEGIN_RING(3 + sz * 4); | ||
396 | OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); | 417 | OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); |
397 | OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); | 418 | OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); |
398 | OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); | 419 | OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); |
420 | ADVANCE_RING(); | ||
399 | 421 | ||
422 | BEGIN_RING(2); | ||
423 | OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); | ||
424 | OUT_RING(0); | ||
400 | ADVANCE_RING(); | 425 | ADVANCE_RING(); |
401 | 426 | ||
402 | cmdbuf->buf += sz * 16; | 427 | cmdbuf->buf += sz * 16; |
@@ -424,6 +449,15 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, | |||
424 | OUT_RING_TABLE((int *)cmdbuf->buf, 8); | 449 | OUT_RING_TABLE((int *)cmdbuf->buf, 8); |
425 | ADVANCE_RING(); | 450 | ADVANCE_RING(); |
426 | 451 | ||
452 | BEGIN_RING(4); | ||
453 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
454 | OUT_RING(R300_RB3D_DC_FLUSH); | ||
455 | OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
456 | OUT_RING(RADEON_WAIT_3D_IDLECLEAN); | ||
457 | ADVANCE_RING(); | ||
458 | /* set flush flag */ | ||
459 | dev_priv->track_flush |= RADEON_FLUSH_EMITED; | ||
460 | |||
427 | cmdbuf->buf += 8 * 4; | 461 | cmdbuf->buf += 8 * 4; |
428 | cmdbuf->bufsz -= 8 * 4; | 462 | cmdbuf->bufsz -= 8 * 4; |
429 | 463 | ||
@@ -613,11 +647,19 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | |||
613 | case RADEON_CNTL_BITBLT_MULTI: | 647 | case RADEON_CNTL_BITBLT_MULTI: |
614 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); | 648 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); |
615 | 649 | ||
616 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | 650 | case RADEON_CP_INDX_BUFFER: |
651 | /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
617 | return r300_emit_indx_buffer(dev_priv, cmdbuf); | 652 | return r300_emit_indx_buffer(dev_priv, cmdbuf); |
618 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ | 653 | case RADEON_CP_3D_DRAW_IMMD_2: |
619 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ | 654 | /* triggers drawing using in-packet vertex data */ |
620 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ | 655 | case RADEON_CP_3D_DRAW_VBUF_2: |
656 | /* triggers drawing of vertex buffers setup elsewhere */ | ||
657 | case RADEON_CP_3D_DRAW_INDX_2: | ||
658 | /* triggers drawing using indices to vertex buffer */ | ||
659 | /* whenever we send vertex we clear flush & purge */ | ||
660 | dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | | ||
661 | RADEON_PURGE_EMITED); | ||
662 | break; | ||
621 | case RADEON_WAIT_FOR_IDLE: | 663 | case RADEON_WAIT_FOR_IDLE: |
622 | case RADEON_CP_NOP: | 664 | case RADEON_CP_NOP: |
623 | /* these packets are safe */ | 665 | /* these packets are safe */ |
@@ -713,17 +755,53 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, | |||
713 | */ | 755 | */ |
714 | static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) | 756 | static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) |
715 | { | 757 | { |
758 | uint32_t cache_z, cache_3d, cache_2d; | ||
716 | RING_LOCALS; | 759 | RING_LOCALS; |
760 | |||
761 | cache_z = R300_ZC_FLUSH; | ||
762 | cache_2d = R300_RB2D_DC_FLUSH; | ||
763 | cache_3d = R300_RB3D_DC_FLUSH; | ||
764 | if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) { | ||
765 | /* we can purge, primitive where draw since last purge */ | ||
766 | cache_z |= R300_ZC_FREE; | ||
767 | cache_2d |= R300_RB2D_DC_FREE; | ||
768 | cache_3d |= R300_RB3D_DC_FREE; | ||
769 | } | ||
717 | 770 | ||
718 | BEGIN_RING(6); | 771 | /* flush & purge zbuffer */ |
719 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | 772 | BEGIN_RING(2); |
720 | OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A); | ||
721 | OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); | 773 | OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); |
722 | OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE| | 774 | OUT_RING(cache_z); |
723 | R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); | 775 | ADVANCE_RING(); |
724 | OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0)); | 776 | /* flush & purge 3d */ |
725 | OUT_RING(0x0); | 777 | BEGIN_RING(2); |
778 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
779 | OUT_RING(cache_3d); | ||
780 | ADVANCE_RING(); | ||
781 | /* flush & purge texture */ | ||
782 | BEGIN_RING(2); | ||
783 | OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0)); | ||
784 | OUT_RING(0); | ||
785 | ADVANCE_RING(); | ||
786 | /* FIXME: is this one really needed ? */ | ||
787 | BEGIN_RING(2); | ||
788 | OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0)); | ||
789 | OUT_RING(0); | ||
790 | ADVANCE_RING(); | ||
791 | BEGIN_RING(2); | ||
792 | OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
793 | OUT_RING(RADEON_WAIT_3D_IDLECLEAN); | ||
794 | ADVANCE_RING(); | ||
795 | /* flush & purge 2d through E2 as RB2D will trigger lockup */ | ||
796 | BEGIN_RING(4); | ||
797 | OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0)); | ||
798 | OUT_RING(cache_2d); | ||
799 | OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
800 | OUT_RING(RADEON_WAIT_2D_IDLECLEAN | | ||
801 | RADEON_WAIT_HOST_IDLECLEAN); | ||
726 | ADVANCE_RING(); | 802 | ADVANCE_RING(); |
803 | /* set flush & purge flags */ | ||
804 | dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; | ||
727 | } | 805 | } |
728 | 806 | ||
729 | /** | 807 | /** |
@@ -905,8 +983,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, | |||
905 | 983 | ||
906 | DRM_DEBUG("\n"); | 984 | DRM_DEBUG("\n"); |
907 | 985 | ||
908 | /* See the comment above r300_emit_begin3d for why this call must be here, | 986 | /* pacify */ |
909 | * and what the cleanup gotos are for. */ | ||
910 | r300_pacify(dev_priv); | 987 | r300_pacify(dev_priv); |
911 | 988 | ||
912 | if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { | 989 | if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { |