1 /*
2 * Copyright © 2019 Google, Inc.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef FD6_PACK_H
7 #define FD6_PACK_H
8
9 #include "a6xx.xml.h"
10
11 struct fd_reg_pair {
12 uint32_t reg;
13 uint64_t value;
14 struct fd_bo *bo;
15 bool is_address;
16 bool bo_write;
17 uint32_t bo_offset;
18 uint32_t bo_shift;
19 uint32_t bo_low;
20 };
21
22 #define __bo_type struct fd_bo *
23
24 #include "a6xx-pack.xml.h"
25 #include "adreno-pm4-pack.xml.h"
26
27 #define __assert_eq(a, b) \
28 do { \
29 if ((a) != (b)) { \
30 fprintf(stderr, "assert failed: " #a " (0x%x) != " #b " (0x%x)\n", a, \
31 b); \
32 assert((a) == (b)); \
33 } \
34 } while (0)
35
36 #if !FD_BO_NO_HARDPIN
37 # error 'Hardpin unsupported'
38 #endif
39
40 static inline uint64_t
__reg_iova(const struct fd_reg_pair * reg)41 __reg_iova(const struct fd_reg_pair *reg)
42 {
43 uint64_t iova = __reloc_iova((struct fd_bo *)reg->bo,
44 reg->bo_offset, 0,
45 -reg->bo_shift);
46 return iova << reg->bo_low;
47 }
48
49 #define __ONE_REG(ring, i, ...) \
50 do { \
51 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
52 /* NOTE: allow __regs[0].reg==0, this happens in OUT_PKT() */ \
53 if (i < ARRAY_SIZE(__regs) && (i == 0 || __regs[i].reg > 0)) { \
54 __assert_eq(__regs[0].reg + i, __regs[i].reg); \
55 if (__regs[i].bo) { \
56 uint64_t *__p64 = (uint64_t *)__p; \
57 *__p64 = __reg_iova(&__regs[i]) | __regs[i].value; \
58 __p += 2; \
59 fd_ringbuffer_assert_attached(ring, __regs[i].bo); \
60 } else { \
61 *__p++ = __regs[i].value; \
62 if (__regs[i].is_address) \
63 *__p++ = __regs[i].value >> 32; \
64 } \
65 } \
66 } while (0)
67
68 #define OUT_REG(ring, ...) \
69 do { \
70 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
71 unsigned count = ARRAY_SIZE(__regs); \
72 \
73 STATIC_ASSERT(ARRAY_SIZE(__regs) > 0); \
74 STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \
75 \
76 BEGIN_RING(ring, count + 1); \
77 uint32_t *__p = ring->cur; \
78 *__p++ = pm4_pkt4_hdr((uint16_t)__regs[0].reg, (uint16_t)count); \
79 \
80 __ONE_REG(ring, 0, __VA_ARGS__); \
81 __ONE_REG(ring, 1, __VA_ARGS__); \
82 __ONE_REG(ring, 2, __VA_ARGS__); \
83 __ONE_REG(ring, 3, __VA_ARGS__); \
84 __ONE_REG(ring, 4, __VA_ARGS__); \
85 __ONE_REG(ring, 5, __VA_ARGS__); \
86 __ONE_REG(ring, 6, __VA_ARGS__); \
87 __ONE_REG(ring, 7, __VA_ARGS__); \
88 __ONE_REG(ring, 8, __VA_ARGS__); \
89 __ONE_REG(ring, 9, __VA_ARGS__); \
90 __ONE_REG(ring, 10, __VA_ARGS__); \
91 __ONE_REG(ring, 11, __VA_ARGS__); \
92 __ONE_REG(ring, 12, __VA_ARGS__); \
93 __ONE_REG(ring, 13, __VA_ARGS__); \
94 __ONE_REG(ring, 14, __VA_ARGS__); \
95 __ONE_REG(ring, 15, __VA_ARGS__); \
96 ring->cur = __p; \
97 } while (0)
98
99 #define OUT_PKT(ring, opcode, ...) \
100 do { \
101 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
102 unsigned count = ARRAY_SIZE(__regs); \
103 \
104 STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \
105 \
106 BEGIN_RING(ring, count + 1); \
107 uint32_t *__p = ring->cur; \
108 *__p++ = pm4_pkt7_hdr(opcode, count); \
109 \
110 __ONE_REG(ring, 0, __VA_ARGS__); \
111 __ONE_REG(ring, 1, __VA_ARGS__); \
112 __ONE_REG(ring, 2, __VA_ARGS__); \
113 __ONE_REG(ring, 3, __VA_ARGS__); \
114 __ONE_REG(ring, 4, __VA_ARGS__); \
115 __ONE_REG(ring, 5, __VA_ARGS__); \
116 __ONE_REG(ring, 6, __VA_ARGS__); \
117 __ONE_REG(ring, 7, __VA_ARGS__); \
118 __ONE_REG(ring, 8, __VA_ARGS__); \
119 __ONE_REG(ring, 9, __VA_ARGS__); \
120 __ONE_REG(ring, 10, __VA_ARGS__); \
121 __ONE_REG(ring, 11, __VA_ARGS__); \
122 __ONE_REG(ring, 12, __VA_ARGS__); \
123 __ONE_REG(ring, 13, __VA_ARGS__); \
124 __ONE_REG(ring, 14, __VA_ARGS__); \
125 __ONE_REG(ring, 15, __VA_ARGS__); \
126 ring->cur = __p; \
127 } while (0)
128
129 /* similar to OUT_PKT() but appends specified # of dwords
130 * copied for buf to the end of the packet (ie. for use-
131 * cases like CP_LOAD_STATE)
132 */
133 #define OUT_PKTBUF(ring, opcode, dwords, sizedwords, ...) \
134 do { \
135 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
136 unsigned count = ARRAY_SIZE(__regs); \
137 \
138 STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \
139 count += sizedwords; \
140 \
141 BEGIN_RING(ring, count + 1); \
142 uint32_t *__p = ring->cur; \
143 *__p++ = pm4_pkt7_hdr(opcode, count); \
144 \
145 __ONE_REG(ring, 0, __VA_ARGS__); \
146 __ONE_REG(ring, 1, __VA_ARGS__); \
147 __ONE_REG(ring, 2, __VA_ARGS__); \
148 __ONE_REG(ring, 3, __VA_ARGS__); \
149 __ONE_REG(ring, 4, __VA_ARGS__); \
150 __ONE_REG(ring, 5, __VA_ARGS__); \
151 __ONE_REG(ring, 6, __VA_ARGS__); \
152 __ONE_REG(ring, 7, __VA_ARGS__); \
153 __ONE_REG(ring, 8, __VA_ARGS__); \
154 __ONE_REG(ring, 9, __VA_ARGS__); \
155 __ONE_REG(ring, 10, __VA_ARGS__); \
156 __ONE_REG(ring, 11, __VA_ARGS__); \
157 __ONE_REG(ring, 12, __VA_ARGS__); \
158 __ONE_REG(ring, 13, __VA_ARGS__); \
159 __ONE_REG(ring, 14, __VA_ARGS__); \
160 __ONE_REG(ring, 15, __VA_ARGS__); \
161 memcpy(__p, dwords, 4 * sizedwords); \
162 __p += sizedwords; \
163 ring->cur = __p; \
164 } while (0)
165
166 #define OUT_BUF(ring, dwords, sizedwords) \
167 do { \
168 uint32_t *__p = ring->cur; \
169 memcpy(__p, dwords, 4 * sizedwords); \
170 __p += sizedwords; \
171 ring->cur = __p; \
172 } while (0)
173
174 #endif /* FD6_PACK_H */
175