drm/radeon: add hier-z registers for r300 and r500 chipsets
[deliverable/linux.git] / drivers / char / drm / r300_cmdbuf.c
index 59b2944811c50c7c9e0269585ba525ce88a49a4e..702df45320f7bcc897439e8b38a1f8d74200c5c4 100644 (file)
@@ -77,23 +77,31 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
                                return -EFAULT;
                        }
 
-                       box.x1 =
-                           (box.x1 +
-                            R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
-                       box.y1 =
-                           (box.y1 +
-                            R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
-                       box.x2 =
-                           (box.x2 +
-                            R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
-                       box.y2 =
-                           (box.y2 +
-                            R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+                       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
+                               box.x1 = (box.x1) &
+                                       R300_CLIPRECT_MASK;
+                               box.y1 = (box.y1) &
+                                       R300_CLIPRECT_MASK;
+                               box.x2 = (box.x2) &
+                                       R300_CLIPRECT_MASK;
+                               box.y2 = (box.y2) &
+                                       R300_CLIPRECT_MASK;
+                       } else {
+                               box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
+                               box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
+                               box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
+                               box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
 
+                       }
                        OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
                                 (box.y1 << R300_CLIPRECT_Y_SHIFT));
                        OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
                                 (box.y2 << R300_CLIPRECT_Y_SHIFT));
+
                }
 
                OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
@@ -133,9 +141,11 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
 
 static u8 r300_reg_flags[0x10000 >> 2];
 
-void r300_init_reg_flags(void)
+void r300_init_reg_flags(struct drm_device *dev)
 {
        int i;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
        memset(r300_reg_flags, 0, 0x10000 >> 2);
 #define ADD_RANGE_MARK(reg, count,mark) \
                for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
@@ -179,18 +189,12 @@ void r300_init_reg_flags(void)
        ADD_RANGE(R300_RE_CULL_CNTL, 1);
        ADD_RANGE(0x42C0, 2);
        ADD_RANGE(R300_RS_CNTL_0, 2);
-       ADD_RANGE(R300_RS_INTERP_0, 8);
-       ADD_RANGE(R300_RS_ROUTE_0, 8);
-       ADD_RANGE(0x43A4, 2);
+
+       ADD_RANGE(R300_SC_HYPERZ, 2);
        ADD_RANGE(0x43E8, 1);
-       ADD_RANGE(R300_PFS_CNTL_0, 3);
-       ADD_RANGE(R300_PFS_NODE_0, 4);
-       ADD_RANGE(R300_PFS_TEXI_0, 64);
+
        ADD_RANGE(0x46A4, 5);
-       ADD_RANGE(R300_PFS_INSTR0_0, 64);
-       ADD_RANGE(R300_PFS_INSTR1_0, 64);
-       ADD_RANGE(R300_PFS_INSTR2_0, 64);
-       ADD_RANGE(R300_PFS_INSTR3_0, 64);
+
        ADD_RANGE(R300_RE_FOG_STATE, 1);
        ADD_RANGE(R300_FOG_COLOR_R, 3);
        ADD_RANGE(R300_PP_ALPHA_TEST, 2);
@@ -205,14 +209,12 @@ void r300_init_reg_flags(void)
        ADD_RANGE(0x4E50, 9);
        ADD_RANGE(0x4E88, 1);
        ADD_RANGE(0x4EA0, 2);
-       ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
-       ADD_RANGE(R300_RB3D_ZSTENCIL_FORMAT, 4);
-       ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);    /* check offset */
-       ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
-       ADD_RANGE(0x4F28, 1);
-       ADD_RANGE(0x4F30, 2);
-       ADD_RANGE(0x4F44, 1);
-       ADD_RANGE(0x4F54, 1);
+       ADD_RANGE(R300_ZB_CNTL, 3);
+       ADD_RANGE(R300_ZB_FORMAT, 4);
+       ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);      /* check offset */
+       ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
+       ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
+       ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
 
        ADD_RANGE(R300_TX_FILTER_0, 16);
        ADD_RANGE(R300_TX_FILTER1_0, 16);
@@ -225,11 +227,33 @@ void r300_init_reg_flags(void)
        ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
 
        /* Sporadic registers used as primitives are emitted */
-       ADD_RANGE(R300_RB3D_ZCACHE_CTLSTAT, 1);
+       ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
        ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
        ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
        ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
 
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
+               ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
+               ADD_RANGE(R500_US_CONFIG, 2);
+               ADD_RANGE(R500_US_CODE_ADDR, 3);
+               ADD_RANGE(R500_US_FC_CTRL, 1);
+               ADD_RANGE(R500_RS_IP_0, 16);
+               ADD_RANGE(R500_RS_INST_0, 16);
+               ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
+               ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
+               ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
+       } else {
+               ADD_RANGE(R300_PFS_CNTL_0, 3);
+               ADD_RANGE(R300_PFS_NODE_0, 4);
+               ADD_RANGE(R300_PFS_TEXI_0, 64);
+               ADD_RANGE(R300_PFS_INSTR0_0, 64);
+               ADD_RANGE(R300_PFS_INSTR1_0, 64);
+               ADD_RANGE(R300_PFS_INSTR2_0, 64);
+               ADD_RANGE(R300_PFS_INSTR3_0, 64);
+               ADD_RANGE(R300_RS_INTERP_0, 8);
+               ADD_RANGE(R300_RS_ROUTE_0, 8);
+
+       }
 }
 
 static __inline__ int r300_check_range(unsigned reg, int count)
@@ -486,7 +510,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
        if (cmd[0] & 0x8000) {
                u32 offset;
 
-               if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL 
+               if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
                              | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
                        offset = cmd[2] << 10;
                        ret = !radeon_check_offset(dev_priv, offset);
@@ -504,7 +528,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
                                DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
                                return -EINVAL;
                        }
-                       
+
                }
        }
 
@@ -694,8 +718,9 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
        BEGIN_RING(6);
        OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
        OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
-       OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
-       OUT_RING(R300_RB3D_ZCACHE_UNKNOWN_03);
+       OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
+       OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE|
+                R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
        OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
        OUT_RING(0x0);
        ADVANCE_RING();
@@ -716,6 +741,47 @@ static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
        buf->used = 0;
 }
 
+static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
+                         drm_r300_cmd_header_t header)
+{
+       u32 wait_until;
+       RING_LOCALS;
+
+       if (!header.wait.flags)
+               return;
+
+       wait_until = 0;
+
+       switch(header.wait.flags) {
+       case R300_WAIT_2D:
+               wait_until = RADEON_WAIT_2D_IDLE;
+               break;
+       case R300_WAIT_3D:
+               wait_until = RADEON_WAIT_3D_IDLE;
+               break;
+       case R300_NEW_WAIT_2D_3D:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
+               break;
+       case R300_NEW_WAIT_2D_2D_CLEAN:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+               break;
+       case R300_NEW_WAIT_3D_3D_CLEAN:
+               wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+               break;
+       case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+               wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+               break;
+       default:
+               return;
+       }
+
+       BEGIN_RING(2);
+       OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+       OUT_RING(wait_until);
+       ADVANCE_RING();
+}
+
 static int r300_scratch(drm_radeon_private_t *dev_priv,
                        drm_radeon_kcmd_buffer_t *cmdbuf,
                        drm_r300_cmd_header_t header)
@@ -723,57 +789,105 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
        u32 *ref_age_base;
        u32 i, buf_idx, h_pending;
        RING_LOCALS;
-       
-       if (cmdbuf->bufsz < 
+
+       if (cmdbuf->bufsz <
            (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
                return -EINVAL;
        }
-       
+
        if (header.scratch.reg >= 5) {
                return -EINVAL;
        }
-       
+
        dev_priv->scratch_ages[header.scratch.reg]++;
-       
+
        ref_age_base =  (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
-       
+
        cmdbuf->buf += sizeof(u64);
        cmdbuf->bufsz -= sizeof(u64);
-       
+
        for (i=0; i < header.scratch.n_bufs; i++) {
                buf_idx = *(u32 *)cmdbuf->buf;
                buf_idx *= 2; /* 8 bytes per buf */
-               
+
                if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
                        return -EINVAL;
                }
-                                       
+
                if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
                        return -EINVAL;
                }
-                                       
+
                if (h_pending == 0) {
                        return -EINVAL;
                }
-                                       
+
                h_pending--;
-                                               
+
                if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
                        return -EINVAL;
                }
-                                       
+
                cmdbuf->buf += sizeof(buf_idx);
                cmdbuf->bufsz -= sizeof(buf_idx);
        }
-       
+
        BEGIN_RING(2);
        OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
        OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
        ADVANCE_RING();
-       
+
+       return 0;
+}
+
+/**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
+                                      drm_radeon_kcmd_buffer_t *cmdbuf,
+                                      drm_r300_cmd_header_t header)
+{
+       int sz;
+       int addr;
+       int type;
+       int clamp;
+       int stride;
+       RING_LOCALS;
+
+       sz = header.r500fp.count;
+       /* address is 9 bits 0 - 8, bit 1 of flags is part of address */
+       addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
+
+       type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
+       clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
+
+       addr |= (type << 16);
+       addr |= (clamp << 17);
+
+       stride = type ? 4 : 6;
+
+       DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
+       if (!sz)
+               return 0;
+       if (sz * stride * 4 > cmdbuf->bufsz)
+               return -EINVAL;
+
+       BEGIN_RING(3 + sz * stride);
+       OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
+       OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
+       OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
+
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * stride * 4;
+       cmdbuf->bufsz -= sz * stride * 4;
+
        return 0;
 }
 
+
 /**
  * Parses and validates a user-supplied command buffer and emits appropriate
  * commands on the DMA ring buffer.
@@ -896,19 +1010,8 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
                        break;
 
                case R300_CMD_WAIT:
-                       /* simple enough, we can do it here */
                        DRM_DEBUG("R300_CMD_WAIT\n");
-                       if (header.wait.flags == 0)
-                               break;  /* nothing to do */
-
-                       {
-                               RING_LOCALS;
-
-                               BEGIN_RING(2);
-                               OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-                               OUT_RING((header.wait.flags & 0xf) << 14);
-                               ADVANCE_RING();
-                       }
+                       r300_cmd_wait(dev_priv, header);
                        break;
 
                case R300_CMD_SCRATCH:
@@ -919,7 +1022,20 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
                                goto cleanup;
                        }
                        break;
-                       
+
+               case R300_CMD_R500FP:
+                       if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
+                               DRM_ERROR("Calling r500 command on r300 card\n");
+                               ret = -EINVAL;
+                               goto cleanup;
+                       }
+                       DRM_DEBUG("R300_CMD_R500FP\n");
+                       ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
+                       if (ret) {
+                               DRM_ERROR("r300_emit_r500fp failed\n");
+                               goto cleanup;
+                       }
+                       break;
                default:
                        DRM_ERROR("bad cmd_type %i at %p\n",
                                  header.header.cmd_type,
This page took 0.032599 seconds and 5 git commands to generate.