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, \ 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