xref: /aosp_15_r20/external/mesa3d/src/freedreno/common/fd6_pack.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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