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