• 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 };
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, b); \
48 			assert((a) == (b));											\
49 		}																\
50 	} while (0)
51 
52 #define __ONE_REG(i, ...)											\
53 	do {															\
54 		const struct fd_reg_pair regs[] = { __VA_ARGS__ };			\
55 		/* NOTE: allow regs[0].reg==0, this happens in OUT_PKT() */	\
56 		if (i < ARRAY_SIZE(regs) && (i == 0 || regs[i].reg > 0)) {	\
57 			__assert_eq(regs[0].reg + i, regs[i].reg);				\
58 			if (regs[i].bo) {										\
59 				struct fd_reloc reloc = {							\
60 					.bo = regs[i].bo,								\
61 					.offset = regs[i].bo_offset,					\
62 					.or = regs[i].value,							\
63 					.shift = regs[i].bo_shift,						\
64 					.orhi = regs[i].value >> 32						\
65 				};													\
66 				ring->cur = p;										\
67 				p += 2;												\
68 				fd_ringbuffer_reloc(ring, &reloc);					\
69 			} else {												\
70 				*p++ = regs[i].value;								\
71 				if (regs[i].is_address)								\
72 					*p++ = regs[i].value >> 32;						\
73 			}														\
74 		}															\
75 	} while (0)
76 
77 #define OUT_REG(ring, ...)									\
78 	do {													\
79 		const struct fd_reg_pair regs[] = { __VA_ARGS__ };	\
80 		unsigned count = ARRAY_SIZE(regs);					\
81 															\
82 		STATIC_ASSERT(count > 0);							\
83 		STATIC_ASSERT(count <= 16);							\
84 															\
85 		BEGIN_RING(ring, count + 1);						\
86 		uint32_t *p = ring->cur;							\
87 		*p++ = CP_TYPE4_PKT | count |						\
88 			(_odd_parity_bit(count) << 7) |					\
89 			((regs[0].reg & 0x3ffff) << 8) |				\
90 			((_odd_parity_bit(regs[0].reg) << 27));			\
91 															\
92 		__ONE_REG( 0, __VA_ARGS__);							\
93 		__ONE_REG( 1, __VA_ARGS__);							\
94 		__ONE_REG( 2, __VA_ARGS__);							\
95 		__ONE_REG( 3, __VA_ARGS__);							\
96 		__ONE_REG( 4, __VA_ARGS__);							\
97 		__ONE_REG( 5, __VA_ARGS__);							\
98 		__ONE_REG( 6, __VA_ARGS__);							\
99 		__ONE_REG( 7, __VA_ARGS__);							\
100 		__ONE_REG( 8, __VA_ARGS__);							\
101 		__ONE_REG( 9, __VA_ARGS__);							\
102 		__ONE_REG(10, __VA_ARGS__);							\
103 		__ONE_REG(11, __VA_ARGS__);							\
104 		__ONE_REG(12, __VA_ARGS__);							\
105 		__ONE_REG(13, __VA_ARGS__);							\
106 		__ONE_REG(14, __VA_ARGS__);							\
107 		__ONE_REG(15, __VA_ARGS__);							\
108 		ring->cur = p;										\
109 	} while (0)
110 
111 #define OUT_PKT(ring, opcode, ...)							\
112 	do {													\
113 		const struct fd_reg_pair regs[] = { __VA_ARGS__ };	\
114 		unsigned count = ARRAY_SIZE(regs);					\
115 															\
116 		STATIC_ASSERT(count <= 16);							\
117 															\
118 		BEGIN_RING(ring, count + 1);						\
119 		uint32_t *p = ring->cur;							\
120 		*p++ = CP_TYPE7_PKT | count |						\
121 			(_odd_parity_bit(count) << 15) |				\
122 			((opcode & 0x7f) << 16) |						\
123 			((_odd_parity_bit(opcode) << 23));				\
124 															\
125 		__ONE_REG( 0, __VA_ARGS__);							\
126 		__ONE_REG( 1, __VA_ARGS__);							\
127 		__ONE_REG( 2, __VA_ARGS__);							\
128 		__ONE_REG( 3, __VA_ARGS__);							\
129 		__ONE_REG( 4, __VA_ARGS__);							\
130 		__ONE_REG( 5, __VA_ARGS__);							\
131 		__ONE_REG( 6, __VA_ARGS__);							\
132 		__ONE_REG( 7, __VA_ARGS__);							\
133 		__ONE_REG( 8, __VA_ARGS__);							\
134 		__ONE_REG( 9, __VA_ARGS__);							\
135 		__ONE_REG(10, __VA_ARGS__);							\
136 		__ONE_REG(11, __VA_ARGS__);							\
137 		__ONE_REG(12, __VA_ARGS__);							\
138 		__ONE_REG(13, __VA_ARGS__);							\
139 		__ONE_REG(14, __VA_ARGS__);							\
140 		__ONE_REG(15, __VA_ARGS__);							\
141 		ring->cur = p;										\
142 	} while (0)
143 
144 /* similar to OUT_PKT() but appends specified # of dwords
145  * copied for buf to the end of the packet (ie. for use-
146  * cases like CP_LOAD_STATE)
147  */
148 #define OUT_PKTBUF(ring, opcode, dwords, sizedwords, ...)	\
149 	do {													\
150 		const struct fd_reg_pair regs[] = { __VA_ARGS__ };	\
151 		unsigned count = ARRAY_SIZE(regs);					\
152 															\
153 		STATIC_ASSERT(count <= 16);							\
154 		count += sizedwords;								\
155 															\
156 		BEGIN_RING(ring, count + 1);						\
157 		uint32_t *p = ring->cur;							\
158 		*p++ = CP_TYPE7_PKT | count |						\
159 			(_odd_parity_bit(count) << 15) |				\
160 			((opcode & 0x7f) << 16) |						\
161 			((_odd_parity_bit(opcode) << 23));				\
162 															\
163 		__ONE_REG( 0, __VA_ARGS__);							\
164 		__ONE_REG( 1, __VA_ARGS__);							\
165 		__ONE_REG( 2, __VA_ARGS__);							\
166 		__ONE_REG( 3, __VA_ARGS__);							\
167 		__ONE_REG( 4, __VA_ARGS__);							\
168 		__ONE_REG( 5, __VA_ARGS__);							\
169 		__ONE_REG( 6, __VA_ARGS__);							\
170 		__ONE_REG( 7, __VA_ARGS__);							\
171 		__ONE_REG( 8, __VA_ARGS__);							\
172 		__ONE_REG( 9, __VA_ARGS__);							\
173 		__ONE_REG(10, __VA_ARGS__);							\
174 		__ONE_REG(11, __VA_ARGS__);							\
175 		__ONE_REG(12, __VA_ARGS__);							\
176 		__ONE_REG(13, __VA_ARGS__);							\
177 		__ONE_REG(14, __VA_ARGS__);							\
178 		__ONE_REG(15, __VA_ARGS__);							\
179 		memcpy(p, dwords, 4 * sizedwords);					\
180 		p += sizedwords;									\
181 		ring->cur = p;										\
182 	} while (0)
183 
184 #endif /* FD6_PACK_H */
185