| /* |
| * Copyright © 2019 Google, Inc. |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| #ifndef FD6_PACK_H |
| #define FD6_PACK_H |
| |
| #include "a6xx.xml.h" |
| |
| struct fd_reg_pair { |
| uint32_t reg; |
| uint64_t value; |
| struct fd_bo *bo; |
| bool is_address; |
| bool bo_write; |
| uint32_t bo_offset; |
| uint32_t bo_shift; |
| uint32_t bo_low; |
| }; |
| |
| #define __bo_type struct fd_bo * |
| |
| #include "a6xx-pack.xml.h" |
| #include "adreno-pm4-pack.xml.h" |
| |
| #define __assert_eq(a, b) \ |
| do { \ |
| if ((a) != (b)) { \ |
| fprintf(stderr, "assert failed: " #a " (0x%x) != " #b " (0x%x)\n", a, \ |
| b); \ |
| assert((a) == (b)); \ |
| } \ |
| } while (0) |
| |
| #if !FD_BO_NO_HARDPIN |
| # error 'Hardpin unsupported' |
| #endif |
| |
| static inline uint64_t |
| __reg_iova(const struct fd_reg_pair *reg) |
| { |
| uint64_t iova = __reloc_iova((struct fd_bo *)reg->bo, |
| reg->bo_offset, 0, |
| -reg->bo_shift); |
| return iova << reg->bo_low; |
| } |
| |
| #define __ONE_REG(ring, i, ...) \ |
| do { \ |
| const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \ |
| /* NOTE: allow __regs[0].reg==0, this happens in OUT_PKT() */ \ |
| if (i < ARRAY_SIZE(__regs) && (i == 0 || __regs[i].reg > 0)) { \ |
| __assert_eq(__regs[0].reg + i, __regs[i].reg); \ |
| if (__regs[i].bo) { \ |
| uint64_t *__p64 = (uint64_t *)__p; \ |
| *__p64 = __reg_iova(&__regs[i]) | __regs[i].value; \ |
| __p += 2; \ |
| fd_ringbuffer_assert_attached(ring, __regs[i].bo); \ |
| } else { \ |
| *__p++ = __regs[i].value; \ |
| if (__regs[i].is_address) \ |
| *__p++ = __regs[i].value >> 32; \ |
| } \ |
| } \ |
| } while (0) |
| |
| #define OUT_REG(ring, ...) \ |
| do { \ |
| const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \ |
| unsigned count = ARRAY_SIZE(__regs); \ |
| \ |
| STATIC_ASSERT(ARRAY_SIZE(__regs) > 0); \ |
| STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \ |
| \ |
| BEGIN_RING(ring, count + 1); \ |
| uint32_t *__p = ring->cur; \ |
| *__p++ = pm4_pkt4_hdr((uint16_t)__regs[0].reg, (uint16_t)count); \ |
| \ |
| __ONE_REG(ring, 0, __VA_ARGS__); \ |
| __ONE_REG(ring, 1, __VA_ARGS__); \ |
| __ONE_REG(ring, 2, __VA_ARGS__); \ |
| __ONE_REG(ring, 3, __VA_ARGS__); \ |
| __ONE_REG(ring, 4, __VA_ARGS__); \ |
| __ONE_REG(ring, 5, __VA_ARGS__); \ |
| __ONE_REG(ring, 6, __VA_ARGS__); \ |
| __ONE_REG(ring, 7, __VA_ARGS__); \ |
| __ONE_REG(ring, 8, __VA_ARGS__); \ |
| __ONE_REG(ring, 9, __VA_ARGS__); \ |
| __ONE_REG(ring, 10, __VA_ARGS__); \ |
| __ONE_REG(ring, 11, __VA_ARGS__); \ |
| __ONE_REG(ring, 12, __VA_ARGS__); \ |
| __ONE_REG(ring, 13, __VA_ARGS__); \ |
| __ONE_REG(ring, 14, __VA_ARGS__); \ |
| __ONE_REG(ring, 15, __VA_ARGS__); \ |
| ring->cur = __p; \ |
| } while (0) |
| |
| #define OUT_PKT(ring, opcode, ...) \ |
| do { \ |
| const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \ |
| unsigned count = ARRAY_SIZE(__regs); \ |
| \ |
| STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \ |
| \ |
| BEGIN_RING(ring, count + 1); \ |
| uint32_t *__p = ring->cur; \ |
| *__p++ = pm4_pkt7_hdr(opcode, count); \ |
| \ |
| __ONE_REG(ring, 0, __VA_ARGS__); \ |
| __ONE_REG(ring, 1, __VA_ARGS__); \ |
| __ONE_REG(ring, 2, __VA_ARGS__); \ |
| __ONE_REG(ring, 3, __VA_ARGS__); \ |
| __ONE_REG(ring, 4, __VA_ARGS__); \ |
| __ONE_REG(ring, 5, __VA_ARGS__); \ |
| __ONE_REG(ring, 6, __VA_ARGS__); \ |
| __ONE_REG(ring, 7, __VA_ARGS__); \ |
| __ONE_REG(ring, 8, __VA_ARGS__); \ |
| __ONE_REG(ring, 9, __VA_ARGS__); \ |
| __ONE_REG(ring, 10, __VA_ARGS__); \ |
| __ONE_REG(ring, 11, __VA_ARGS__); \ |
| __ONE_REG(ring, 12, __VA_ARGS__); \ |
| __ONE_REG(ring, 13, __VA_ARGS__); \ |
| __ONE_REG(ring, 14, __VA_ARGS__); \ |
| __ONE_REG(ring, 15, __VA_ARGS__); \ |
| ring->cur = __p; \ |
| } while (0) |
| |
| /* similar to OUT_PKT() but appends specified # of dwords |
| * copied for buf to the end of the packet (ie. for use- |
| * cases like CP_LOAD_STATE) |
| */ |
| #define OUT_PKTBUF(ring, opcode, dwords, sizedwords, ...) \ |
| do { \ |
| const struct fd_reg_pair __regs[] = {__VA_ARGS__}; \ |
| unsigned count = ARRAY_SIZE(__regs); \ |
| \ |
| STATIC_ASSERT(ARRAY_SIZE(__regs) <= 16); \ |
| count += sizedwords; \ |
| \ |
| BEGIN_RING(ring, count + 1); \ |
| uint32_t *__p = ring->cur; \ |
| *__p++ = pm4_pkt7_hdr(opcode, count); \ |
| \ |
| __ONE_REG(ring, 0, __VA_ARGS__); \ |
| __ONE_REG(ring, 1, __VA_ARGS__); \ |
| __ONE_REG(ring, 2, __VA_ARGS__); \ |
| __ONE_REG(ring, 3, __VA_ARGS__); \ |
| __ONE_REG(ring, 4, __VA_ARGS__); \ |
| __ONE_REG(ring, 5, __VA_ARGS__); \ |
| __ONE_REG(ring, 6, __VA_ARGS__); \ |
| __ONE_REG(ring, 7, __VA_ARGS__); \ |
| __ONE_REG(ring, 8, __VA_ARGS__); \ |
| __ONE_REG(ring, 9, __VA_ARGS__); \ |
| __ONE_REG(ring, 10, __VA_ARGS__); \ |
| __ONE_REG(ring, 11, __VA_ARGS__); \ |
| __ONE_REG(ring, 12, __VA_ARGS__); \ |
| __ONE_REG(ring, 13, __VA_ARGS__); \ |
| __ONE_REG(ring, 14, __VA_ARGS__); \ |
| __ONE_REG(ring, 15, __VA_ARGS__); \ |
| memcpy(__p, dwords, 4 * sizedwords); \ |
| __p += sizedwords; \ |
| ring->cur = __p; \ |
| } while (0) |
| |
| #define OUT_BUF(ring, dwords, sizedwords) \ |
| do { \ |
| uint32_t *__p = ring->cur; \ |
| memcpy(__p, dwords, 4 * sizedwords); \ |
| __p += sizedwords; \ |
| ring->cur = __p; \ |
| } while (0) |
| |
| #endif /* FD6_PACK_H */ |