1 /*
2 * Copyright © 2019 Google, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #ifndef FD6_PACK_H
25 #define FD6_PACK_H
26
27 #include "a6xx.xml.h"
28
29 struct fd_reg_pair {
30 uint32_t reg;
31 uint64_t value;
32 struct fd_bo *bo;
33 bool is_address;
34 bool bo_write;
35 uint32_t bo_offset;
36 uint32_t bo_shift;
37 uint32_t bo_low;
38 };
39
40 #define __bo_type struct fd_bo *
41
42 #include "a6xx-pack.xml.h"
43 #include "adreno-pm4-pack.xml.h"
44
45 #define __assert_eq(a, b) \
46 do { \
47 if ((a) != (b)) { \
48 fprintf(stderr, "assert failed: " #a " (0x%x) != " #b " (0x%x)\n", a, \
49 b); \
50 assert((a) == (b)); \
51 } \
52 } while (0)
53
54 #if !FD_BO_NO_HARDPIN
55 # error 'Hardpin unsupported'
56 #endif
57
58 static inline uint64_t
__reg_iova(const struct fd_reg_pair * reg)59 __reg_iova(const struct fd_reg_pair *reg)
60 {
61 uint64_t iova = __reloc_iova((struct fd_bo *)reg->bo,
62 reg->bo_offset, 0,
63 -reg->bo_shift);
64 return iova << reg->bo_low;
65 }
66
67 #define __ONE_REG(ring, i, ...) \
68 do { \
69 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
70 /* NOTE: allow __regs[0].reg==0, this happens in OUT_PKT() */ \
71 if (i < ARRAY_SIZE(__regs) && (i == 0 || __regs[i].reg > 0)) { \
72 __assert_eq(__regs[0].reg + i, __regs[i].reg); \
73 if (__regs[i].bo) { \
74 uint64_t *__p64 = (uint64_t *)__p; \
75 *__p64 = __reg_iova(&__regs[i]) | __regs[i].value; \
76 __p += 2; \
77 fd_ringbuffer_assert_attached(ring, __regs[i].bo); \
78 } else { \
79 *__p++ = __regs[i].value; \
80 if (__regs[i].is_address) \
81 *__p++ = __regs[i].value >> 32; \
82 } \
83 } \
84 } while (0)
85
86 #define OUT_REG(ring, ...) \
87 do { \
88 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
89 unsigned count = ARRAY_SIZE(__regs); \
90 \
91 STATIC_ASSERT(ARRAY_SIZE(__regs) > 0); \
92 STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \
93 \
94 BEGIN_RING(ring, count + 1); \
95 uint32_t *__p = ring->cur; \
96 *__p++ = pm4_pkt4_hdr((uint16_t)__regs[0].reg, (uint16_t)count); \
97 \
98 __ONE_REG(ring, 0, __VA_ARGS__); \
99 __ONE_REG(ring, 1, __VA_ARGS__); \
100 __ONE_REG(ring, 2, __VA_ARGS__); \
101 __ONE_REG(ring, 3, __VA_ARGS__); \
102 __ONE_REG(ring, 4, __VA_ARGS__); \
103 __ONE_REG(ring, 5, __VA_ARGS__); \
104 __ONE_REG(ring, 6, __VA_ARGS__); \
105 __ONE_REG(ring, 7, __VA_ARGS__); \
106 __ONE_REG(ring, 8, __VA_ARGS__); \
107 __ONE_REG(ring, 9, __VA_ARGS__); \
108 __ONE_REG(ring, 10, __VA_ARGS__); \
109 __ONE_REG(ring, 11, __VA_ARGS__); \
110 __ONE_REG(ring, 12, __VA_ARGS__); \
111 __ONE_REG(ring, 13, __VA_ARGS__); \
112 __ONE_REG(ring, 14, __VA_ARGS__); \
113 __ONE_REG(ring, 15, __VA_ARGS__); \
114 ring->cur = __p; \
115 } while (0)
116
117 #define OUT_PKT(ring, opcode, ...) \
118 do { \
119 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
120 unsigned count = ARRAY_SIZE(__regs); \
121 \
122 STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \
123 \
124 BEGIN_RING(ring, count + 1); \
125 uint32_t *__p = ring->cur; \
126 *__p++ = pm4_pkt7_hdr(opcode, count); \
127 \
128 __ONE_REG(ring, 0, __VA_ARGS__); \
129 __ONE_REG(ring, 1, __VA_ARGS__); \
130 __ONE_REG(ring, 2, __VA_ARGS__); \
131 __ONE_REG(ring, 3, __VA_ARGS__); \
132 __ONE_REG(ring, 4, __VA_ARGS__); \
133 __ONE_REG(ring, 5, __VA_ARGS__); \
134 __ONE_REG(ring, 6, __VA_ARGS__); \
135 __ONE_REG(ring, 7, __VA_ARGS__); \
136 __ONE_REG(ring, 8, __VA_ARGS__); \
137 __ONE_REG(ring, 9, __VA_ARGS__); \
138 __ONE_REG(ring, 10, __VA_ARGS__); \
139 __ONE_REG(ring, 11, __VA_ARGS__); \
140 __ONE_REG(ring, 12, __VA_ARGS__); \
141 __ONE_REG(ring, 13, __VA_ARGS__); \
142 __ONE_REG(ring, 14, __VA_ARGS__); \
143 __ONE_REG(ring, 15, __VA_ARGS__); \
144 ring->cur = __p; \
145 } while (0)
146
147 /* similar to OUT_PKT() but appends specified # of dwords
148 * copied for buf to the end of the packet (ie. for use-
149 * cases like CP_LOAD_STATE)
150 */
151 #define OUT_PKTBUF(ring, opcode, dwords, sizedwords, ...) \
152 do { \
153 const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \
154 unsigned count = ARRAY_SIZE(__regs); \
155 \
156 STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \
157 count += sizedwords; \
158 \
159 BEGIN_RING(ring, count + 1); \
160 uint32_t *__p = ring->cur; \
161 *__p++ = pm4_pkt7_hdr(opcode, count); \
162 \
163 __ONE_REG(ring, 0, __VA_ARGS__); \
164 __ONE_REG(ring, 1, __VA_ARGS__); \
165 __ONE_REG(ring, 2, __VA_ARGS__); \
166 __ONE_REG(ring, 3, __VA_ARGS__); \
167 __ONE_REG(ring, 4, __VA_ARGS__); \
168 __ONE_REG(ring, 5, __VA_ARGS__); \
169 __ONE_REG(ring, 6, __VA_ARGS__); \
170 __ONE_REG(ring, 7, __VA_ARGS__); \
171 __ONE_REG(ring, 8, __VA_ARGS__); \
172 __ONE_REG(ring, 9, __VA_ARGS__); \
173 __ONE_REG(ring, 10, __VA_ARGS__); \
174 __ONE_REG(ring, 11, __VA_ARGS__); \
175 __ONE_REG(ring, 12, __VA_ARGS__); \
176 __ONE_REG(ring, 13, __VA_ARGS__); \
177 __ONE_REG(ring, 14, __VA_ARGS__); \
178 __ONE_REG(ring, 15, __VA_ARGS__); \
179 memcpy(__p, dwords, 4 * sizedwords); \
180 __p += sizedwords; \
181 ring->cur = __p; \
182 } while (0)
183
184 #define OUT_BUF(ring, dwords, sizedwords) \
185 do { \
186 uint32_t *__p = ring->cur; \
187 memcpy(__p, dwords, 4 * sizedwords); \
188 __p += sizedwords; \
189 ring->cur = __p; \
190 } while (0)
191
192 #endif /* FD6_PACK_H */
193