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