blob: 64265da28ea8ada5fcfc5c854edd9003374d4e30 [file] [log] [blame] [edit]
/*
* 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 */