]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
drm/radeon: implement common cs packet parse function
authorIlija Hadzic <ihadzic@research.bell-labs.com>
Wed, 2 Jan 2013 23:27:40 +0000 (18:27 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 31 Jan 2013 21:24:41 +0000 (16:24 -0500)
CS packet parse functions have a lot of in common across
all ASICs. Implement a common function and take care of
small differences between families inside the function.

This patch is a prep for major refactoring and consolidation
of CS parsing code.

Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
Reviewed-by: Marek Olšák <maraeo@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_reg.h

index 0a23589e3d4005e8bb9d5b961145e063388d1f18..7355a3613e2351973db3ed3a45d6b4fb50a353bd 100644 (file)
@@ -642,3 +642,56 @@ u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
        idx_value = ibc->kpage[new_page][pg_offset/4];
        return idx_value;
 }
+
+/**
+ * radeon_cs_packet_parse() - parse cp packet and point ib index to next packet
+ * @parser:    parser structure holding parsing context.
+ * @pkt:       where to store packet information
+ *
+ * Assume that chunk_ib_index is properly set. Will return -EINVAL
+ * if packet is bigger than remaining ib size. or if packets is unknown.
+ **/
+int radeon_cs_packet_parse(struct radeon_cs_parser *p,
+                          struct radeon_cs_packet *pkt,
+                          unsigned idx)
+{
+       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+       struct radeon_device *rdev = p->rdev;
+       uint32_t header;
+
+       if (idx >= ib_chunk->length_dw) {
+               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+                         idx, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       header = radeon_get_ib_value(p, idx);
+       pkt->idx = idx;
+       pkt->type = RADEON_CP_PACKET_GET_TYPE(header);
+       pkt->count = RADEON_CP_PACKET_GET_COUNT(header);
+       pkt->one_reg_wr = 0;
+       switch (pkt->type) {
+       case RADEON_PACKET_TYPE0:
+               if (rdev->family < CHIP_R600) {
+                       pkt->reg = R100_CP_PACKET0_GET_REG(header);
+                       pkt->one_reg_wr =
+                               RADEON_CP_PACKET0_GET_ONE_REG_WR(header);
+               } else
+                       pkt->reg = R600_CP_PACKET0_GET_REG(header);
+               break;
+       case RADEON_PACKET_TYPE3:
+               pkt->opcode = RADEON_CP_PACKET3_GET_OPCODE(header);
+               break;
+       case RADEON_PACKET_TYPE2:
+               pkt->count = -1;
+               break;
+       default:
+               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
+               return -EINVAL;
+       }
+       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
+               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
+                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       return 0;
+}
index 5d8f735d6aafe6789189601b41098582fb649814..d9e4204430fbbc58a73dd352445349d4d3da29bf 100644 (file)
 
 #define RV530_GB_PIPE_SELECT2           0x4124
 
+#define RADEON_CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define RADEON_CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define RADEON_CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
+#define RADEON_CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define R100_CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
+#define R600_CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
+#define RADEON_PACKET_TYPE0 0
+#define RADEON_PACKET_TYPE1 1
+#define RADEON_PACKET_TYPE2 2
+#define RADEON_PACKET_TYPE3 3
+
 #endif