aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r300_cmdbuf.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-09-16 17:11:43 -0400
committerDavid S. Miller <davem@davemloft.net>2008-09-16 17:11:43 -0400
commit2e57572a50a4de41c6cbc879a4866a312d4cd316 (patch)
treec4f58ec96c06642c4b415b881d3f0a3b673d5b44 /drivers/gpu/drm/radeon/r300_cmdbuf.c
parent9b2e43ae4e9609f80034dfe8de895045cac52d77 (diff)
parentf948cc6ab9e61a8e88d70ee9aafc690e6d26f92c (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
Conflicts: arch/sparc64/kernel/pci_psycho.c
Diffstat (limited to 'drivers/gpu/drm/radeon/r300_cmdbuf.c')
-rw-r--r--drivers/gpu/drm/radeon/r300_cmdbuf.c196
1 files changed, 162 insertions, 34 deletions
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c
index 702df45320f7..4b27d9abb7bc 100644
--- a/drivers/gpu/drm/radeon/r300_cmdbuf.c
+++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c
@@ -77,6 +77,9 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
77 return -EFAULT; 77 return -EFAULT;
78 } 78 }
79 79
80 box.x2--; /* Hardware expects inclusive bottom-right corner */
81 box.y2--;
82
80 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { 83 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
81 box.x1 = (box.x1) & 84 box.x1 = (box.x1) &
82 R300_CLIPRECT_MASK; 85 R300_CLIPRECT_MASK;
@@ -95,8 +98,8 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
95 R300_CLIPRECT_MASK; 98 R300_CLIPRECT_MASK;
96 box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & 99 box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
97 R300_CLIPRECT_MASK; 100 R300_CLIPRECT_MASK;
98
99 } 101 }
102
100 OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | 103 OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
101 (box.y1 << R300_CLIPRECT_Y_SHIFT)); 104 (box.y1 << R300_CLIPRECT_Y_SHIFT));
102 OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | 105 OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
@@ -136,6 +139,18 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
136 ADVANCE_RING(); 139 ADVANCE_RING();
137 } 140 }
138 141
142 /* flus cache and wait idle clean after cliprect change */
143 BEGIN_RING(2);
144 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
145 OUT_RING(R300_RB3D_DC_FLUSH);
146 ADVANCE_RING();
147 BEGIN_RING(2);
148 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
149 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
150 ADVANCE_RING();
151 /* set flush flag */
152 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
153
139 return 0; 154 return 0;
140} 155}
141 156
@@ -166,13 +181,13 @@ void r300_init_reg_flags(struct drm_device *dev)
166 ADD_RANGE(0x21DC, 1); 181 ADD_RANGE(0x21DC, 1);
167 ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); 182 ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
168 ADD_RANGE(R300_VAP_CLIP_X_0, 4); 183 ADD_RANGE(R300_VAP_CLIP_X_0, 4);
169 ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1); 184 ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
170 ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); 185 ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
171 ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); 186 ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
172 ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); 187 ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
173 ADD_RANGE(R300_GB_ENABLE, 1); 188 ADD_RANGE(R300_GB_ENABLE, 1);
174 ADD_RANGE(R300_GB_MSPOS0, 5); 189 ADD_RANGE(R300_GB_MSPOS0, 5);
175 ADD_RANGE(R300_TX_CNTL, 1); 190 ADD_RANGE(R300_TX_INVALTAGS, 1);
176 ADD_RANGE(R300_TX_ENABLE, 1); 191 ADD_RANGE(R300_TX_ENABLE, 1);
177 ADD_RANGE(0x4200, 4); 192 ADD_RANGE(0x4200, 4);
178 ADD_RANGE(0x4214, 1); 193 ADD_RANGE(0x4214, 1);
@@ -388,15 +403,28 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
388 if (sz * 16 > cmdbuf->bufsz) 403 if (sz * 16 > cmdbuf->bufsz)
389 return -EINVAL; 404 return -EINVAL;
390 405
391 BEGIN_RING(5 + sz * 4); 406 /* VAP is very sensitive so we purge cache before we program it
392 /* Wait for VAP to come to senses.. */ 407 * and we also flush its state before & after */
393 /* there is no need to emit it multiple times, (only once before VAP is programmed, 408 BEGIN_RING(6);
394 but this optimization is for later */ 409 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
395 OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0); 410 OUT_RING(R300_RB3D_DC_FLUSH);
411 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
412 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
413 OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
414 OUT_RING(0);
415 ADVANCE_RING();
416 /* set flush flag */
417 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
418
419 BEGIN_RING(3 + sz * 4);
396 OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); 420 OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
397 OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); 421 OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
398 OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); 422 OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
423 ADVANCE_RING();
399 424
425 BEGIN_RING(2);
426 OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
427 OUT_RING(0);
400 ADVANCE_RING(); 428 ADVANCE_RING();
401 429
402 cmdbuf->buf += sz * 16; 430 cmdbuf->buf += sz * 16;
@@ -424,6 +452,15 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
424 OUT_RING_TABLE((int *)cmdbuf->buf, 8); 452 OUT_RING_TABLE((int *)cmdbuf->buf, 8);
425 ADVANCE_RING(); 453 ADVANCE_RING();
426 454
455 BEGIN_RING(4);
456 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
457 OUT_RING(R300_RB3D_DC_FLUSH);
458 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
459 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
460 ADVANCE_RING();
461 /* set flush flag */
462 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
463
427 cmdbuf->buf += 8 * 4; 464 cmdbuf->buf += 8 * 4;
428 cmdbuf->bufsz -= 8 * 4; 465 cmdbuf->bufsz -= 8 * 4;
429 466
@@ -543,22 +580,23 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
543 return 0; 580 return 0;
544} 581}
545 582
546static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, 583static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
547 drm_radeon_kcmd_buffer_t *cmdbuf) 584 drm_radeon_kcmd_buffer_t *cmdbuf)
548{ 585{
549 u32 *cmd = (u32 *) cmdbuf->buf; 586 u32 *cmd;
550 int count, ret; 587 int count;
588 int expected_count;
551 RING_LOCALS; 589 RING_LOCALS;
552 590
553 count=(cmd[0]>>16) & 0x3fff; 591 cmd = (u32 *) cmdbuf->buf;
592 count = (cmd[0]>>16) & 0x3fff;
593 expected_count = cmd[1] >> 16;
594 if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
595 expected_count = (expected_count+1)/2;
554 596
555 if ((cmd[1] & 0x8000ffff) != 0x80000810) { 597 if (count && count != expected_count) {
556 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); 598 DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
557 return -EINVAL; 599 count, expected_count);
558 }
559 ret = !radeon_check_offset(dev_priv, cmd[2]);
560 if (ret) {
561 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
562 return -EINVAL; 600 return -EINVAL;
563 } 601 }
564 602
@@ -570,6 +608,50 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
570 cmdbuf->buf += (count+2)*4; 608 cmdbuf->buf += (count+2)*4;
571 cmdbuf->bufsz -= (count+2)*4; 609 cmdbuf->bufsz -= (count+2)*4;
572 610
611 if (!count) {
612 drm_r300_cmd_header_t header;
613
614 if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
615 DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
616 return -EINVAL;
617 }
618
619 header.u = *(unsigned int *)cmdbuf->buf;
620
621 cmdbuf->buf += sizeof(header);
622 cmdbuf->bufsz -= sizeof(header);
623 cmd = (u32 *) cmdbuf->buf;
624
625 if (header.header.cmd_type != R300_CMD_PACKET3 ||
626 header.packet3.packet != R300_CMD_PACKET3_RAW ||
627 cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
628 DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
629 return -EINVAL;
630 }
631
632 if ((cmd[1] & 0x8000ffff) != 0x80000810) {
633 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
634 return -EINVAL;
635 }
636 if (!radeon_check_offset(dev_priv, cmd[2])) {
637 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
638 return -EINVAL;
639 }
640 if (cmd[3] != expected_count) {
641 DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
642 cmd[3], expected_count);
643 return -EINVAL;
644 }
645
646 BEGIN_RING(4);
647 OUT_RING(cmd[0]);
648 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
649 ADVANCE_RING();
650
651 cmdbuf->buf += 4*4;
652 cmdbuf->bufsz -= 4*4;
653 }
654
573 return 0; 655 return 0;
574} 656}
575 657
@@ -613,11 +695,22 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
613 case RADEON_CNTL_BITBLT_MULTI: 695 case RADEON_CNTL_BITBLT_MULTI:
614 return r300_emit_bitblt_multi(dev_priv, cmdbuf); 696 return r300_emit_bitblt_multi(dev_priv, cmdbuf);
615 697
616 case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ 698 case RADEON_CP_INDX_BUFFER:
617 return r300_emit_indx_buffer(dev_priv, cmdbuf); 699 DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
618 case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ 700 return -EINVAL;
619 case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ 701 case RADEON_CP_3D_DRAW_IMMD_2:
620 case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ 702 /* triggers drawing using in-packet vertex data */
703 case RADEON_CP_3D_DRAW_VBUF_2:
704 /* triggers drawing of vertex buffers setup elsewhere */
705 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
706 RADEON_PURGE_EMITED);
707 break;
708 case RADEON_CP_3D_DRAW_INDX_2:
709 /* triggers drawing using indices to vertex buffer */
710 /* whenever we send vertex we clear flush & purge */
711 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
712 RADEON_PURGE_EMITED);
713 return r300_emit_draw_indx_2(dev_priv, cmdbuf);
621 case RADEON_WAIT_FOR_IDLE: 714 case RADEON_WAIT_FOR_IDLE:
622 case RADEON_CP_NOP: 715 case RADEON_CP_NOP:
623 /* these packets are safe */ 716 /* these packets are safe */
@@ -713,17 +806,53 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
713 */ 806 */
714static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) 807static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
715{ 808{
809 uint32_t cache_z, cache_3d, cache_2d;
716 RING_LOCALS; 810 RING_LOCALS;
717 811
718 BEGIN_RING(6); 812 cache_z = R300_ZC_FLUSH;
719 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 813 cache_2d = R300_RB2D_DC_FLUSH;
720 OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A); 814 cache_3d = R300_RB3D_DC_FLUSH;
815 if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
816 /* we can purge, primitive where draw since last purge */
817 cache_z |= R300_ZC_FREE;
818 cache_2d |= R300_RB2D_DC_FREE;
819 cache_3d |= R300_RB3D_DC_FREE;
820 }
821
822 /* flush & purge zbuffer */
823 BEGIN_RING(2);
721 OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); 824 OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
722 OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE| 825 OUT_RING(cache_z);
723 R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); 826 ADVANCE_RING();
724 OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0)); 827 /* flush & purge 3d */
725 OUT_RING(0x0); 828 BEGIN_RING(2);
829 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
830 OUT_RING(cache_3d);
831 ADVANCE_RING();
832 /* flush & purge texture */
833 BEGIN_RING(2);
834 OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
835 OUT_RING(0);
836 ADVANCE_RING();
837 /* FIXME: is this one really needed ? */
838 BEGIN_RING(2);
839 OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
840 OUT_RING(0);
841 ADVANCE_RING();
842 BEGIN_RING(2);
843 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
844 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
845 ADVANCE_RING();
846 /* flush & purge 2d through E2 as RB2D will trigger lockup */
847 BEGIN_RING(4);
848 OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
849 OUT_RING(cache_2d);
850 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
851 OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
852 RADEON_WAIT_HOST_IDLECLEAN);
726 ADVANCE_RING(); 853 ADVANCE_RING();
854 /* set flush & purge flags */
855 dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
727} 856}
728 857
729/** 858/**
@@ -905,8 +1034,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
905 1034
906 DRM_DEBUG("\n"); 1035 DRM_DEBUG("\n");
907 1036
908 /* See the comment above r300_emit_begin3d for why this call must be here, 1037 /* pacify */
909 * and what the cleanup gotos are for. */
910 r300_pacify(dev_priv); 1038 r300_pacify(dev_priv);
911 1039
912 if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { 1040 if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {