• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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