20
#include <../arch/arm/armlib/mem_barriers.h>
21
#include <etnaviv_xml/cmdstream.xml.h>
22
#include <etnaviv_xml/common.xml.h>
23
#include <etnaviv_xml/state.xml.h>
24
#include <etnaviv_xml/state_3d.xml.h>
25
#include <etnaviv_xml/state_hi.xml.h>
28
#include "etnaviv_cmdbuf.h"
29
#include "etnaviv_compat.h"
30
#include "etnaviv_drm.h"
31
#include "etnaviv_gem.h"
32
#include "etnaviv_gpu.h"
38
static inline void OUT(struct etnaviv_cmdbuf *buffer, uint32_t data) {
39
uint32_t *vaddr = (uint32_t *)buffer->vaddr;
40
vaddr[buffer->user_size / 4] = data;
41
buffer->user_size += 4;
44
static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer, uint32_t reg,
46
uint32_t index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
48
buffer->user_size = ALIGN(buffer->user_size, 8);
51
OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE
52
| VIV_FE_LOAD_STATE_HEADER_COUNT(1)
53
| VIV_FE_LOAD_STATE_HEADER_OFFSET(index));
57
static inline void CMD_END(struct etnaviv_cmdbuf *buffer) {
58
buffer->user_size = ALIGN(buffer->user_size, 8);
60
OUT(buffer, VIV_FE_END_HEADER_OP_END);
63
static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer) {
64
buffer->user_size = ALIGN(buffer->user_size, 8);
66
OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | 200);
69
static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer, uint16_t prefetch,
71
buffer->user_size = ALIGN(buffer->user_size, 8);
74
VIV_FE_LINK_HEADER_OP_LINK | VIV_FE_LINK_HEADER_PREFETCH(prefetch));
78
static inline void CMD_STALL(struct etnaviv_cmdbuf *buffer, uint32_t from,
80
buffer->user_size = ALIGN(buffer->user_size, 8);
82
OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
83
OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
86
static inline void CMD_SEM(struct etnaviv_cmdbuf *buffer, uint32_t from,
88
CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN,
89
VIVS_GL_SEMAPHORE_TOKEN_FROM(from) | VIVS_GL_SEMAPHORE_TOKEN_TO(to));
92
static void etnaviv_cmd_select_pipe(struct etnaviv_gpu *gpu,
93
struct etnaviv_cmdbuf *buffer, uint8_t pipe) {
102
if (gpu->exec_state == ETNA_PIPE_2D)
103
flush = VIVS_GL_FLUSH_CACHE_PE2D;
104
else if (gpu->exec_state == ETNA_PIPE_3D)
105
flush = VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR;
107
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush);
108
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
109
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
111
CMD_LOAD_STATE(buffer, VIVS_GL_PIPE_SELECT, VIVS_GL_PIPE_SELECT_PIPE(pipe));
114
void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct etnaviv_cmdbuf *buf,
115
uint32_t off, uint32_t len) {
116
uint32_t size = buf->size;
117
uint32_t *ptr = buf->vaddr + off;
120
log_debug("virt %p phys 0x%08" PRIu32 " free 0x%08" PRIu32 "\n", ptr,
121
etnaviv_cmdbuf_get_va(buf) + off, size - len * 4 - off);
123
if (log_level_self() == LOG_NONE) {
127
for (i = 0; i < len / 4; i++) {
131
printk("\t%p: ", ptr + i);
132
printk("%08" PRIu32 " ", *(ptr + i));
144
static void etnaviv_buffer_replace_wait(struct etnaviv_cmdbuf *buffer,
145
unsigned int wl_offset, uint32_t cmd, uint32_t arg) {
146
uint32_t *lw = buffer->vaddr + wl_offset;
157
static uint32_t etnaviv_buffer_reserve(struct etnaviv_gpu *gpu,
158
struct etnaviv_cmdbuf *buffer, unsigned int cmd_dwords) {
159
if (buffer->user_size + cmd_dwords * sizeof(uint64_t) > buffer->size)
160
buffer->user_size = 0;
162
return etnaviv_cmdbuf_get_va(buffer) + buffer->user_size;
165
uint16_t etnaviv_buffer_init(struct etnaviv_gpu *gpu) {
166
struct etnaviv_cmdbuf *buffer = gpu->buffer;
169
buffer->user_size = 0;
172
CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) + buffer->user_size - 4);
174
return buffer->user_size / 8;
177
uint16_t etnaviv_buffer_config_mmuv2(struct etnaviv_gpu *gpu,
178
uint32_t mtlb_addr, uint32_t safe_addr) {
179
struct etnaviv_cmdbuf *buffer = gpu->buffer;
181
buffer->user_size = 0;
183
if (gpu->identity.features & chipFeatures_PIPE_3D) {
184
CMD_LOAD_STATE(buffer, VIVS_GL_PIPE_SELECT,
185
VIVS_GL_PIPE_SELECT_PIPE(ETNA_PIPE_3D));
186
CMD_LOAD_STATE(buffer, VIVS_MMUv2_CONFIGURATION,
187
mtlb_addr | VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K);
188
CMD_LOAD_STATE(buffer, VIVS_MMUv2_SAFE_ADDRESS, safe_addr);
189
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
190
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
193
if (gpu->identity.features & chipFeatures_PIPE_2D) {
194
CMD_LOAD_STATE(buffer, VIVS_GL_PIPE_SELECT,
195
VIVS_GL_PIPE_SELECT_PIPE(ETNA_PIPE_2D));
196
CMD_LOAD_STATE(buffer, VIVS_MMUv2_CONFIGURATION,
197
mtlb_addr | VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K);
198
CMD_LOAD_STATE(buffer, VIVS_MMUv2_SAFE_ADDRESS, safe_addr);
199
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
200
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
205
buffer->user_size = ALIGN(buffer->user_size, 8);
207
return buffer->user_size / 8;
211
void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
212
struct etnaviv_cmdbuf *cmdbuf) {
213
struct etnaviv_cmdbuf *buffer = gpu->buffer;
214
unsigned int waitlink_offset = buffer->user_size - 16;
215
uint32_t return_target, return_dwords;
216
uint32_t link_target, link_dwords;
218
log_debug("exec_state=%d", gpu->exec_state);
219
link_target = etnaviv_cmdbuf_get_va(cmdbuf);
220
link_dwords = cmdbuf->size / 8;
226
if (gpu->mmu.need_flush || gpu->switch_context) {
227
uint32_t target, extra_dwords;
233
if (gpu->mmu.need_flush) {
234
if (gpu->mmu.version == ETNAVIV_IOMMU_V1)
241
if (gpu->switch_context) {
245
target = etnaviv_buffer_reserve(gpu, buffer, extra_dwords);
247
if (gpu->mmu.need_flush) {
249
if (gpu->mmu.version == ETNAVIV_IOMMU_V1) {
250
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_MMU,
251
VIVS_GL_FLUSH_MMU_FLUSH_FEMMU | VIVS_GL_FLUSH_MMU_FLUSH_UNK1
252
| VIVS_GL_FLUSH_MMU_FLUSH_UNK2
253
| VIVS_GL_FLUSH_MMU_FLUSH_PEMMU
254
| VIVS_GL_FLUSH_MMU_FLUSH_UNK4);
257
CMD_LOAD_STATE(buffer, VIVS_MMUv2_CONFIGURATION,
258
VIVS_MMUv2_CONFIGURATION_MODE_MASK
259
| VIVS_MMUv2_CONFIGURATION_ADDRESS_MASK
260
| VIVS_MMUv2_CONFIGURATION_FLUSH_FLUSH);
261
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
262
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
265
gpu->mmu.need_flush = false;
268
if (gpu->switch_context) {
269
etnaviv_cmd_select_pipe(gpu, buffer, cmdbuf->exec_state);
270
gpu->exec_state = cmdbuf->exec_state;
271
gpu->switch_context = false;
275
CMD_LINK(buffer, link_dwords, link_target);
278
link_target = target;
279
link_dwords = extra_dwords;
289
return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords);
290
CMD_LINK(cmdbuf, return_dwords, return_target);
296
if (gpu->exec_state == ETNA_PIPE_2D) {
297
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D);
300
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
301
VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR);
302
CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH);
305
CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
306
CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
307
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT,
308
VIVS_GL_EVENT_EVENT_ID(event) | VIVS_GL_EVENT_FROM_PE);
310
CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) + buffer->user_size - 4);
312
etnaviv_buffer_dump(gpu, buffer, 0, buffer->user_size);
313
log_debug("stream link to 0x%08x @ 0x%08x", return_target,
314
etnaviv_cmdbuf_get_va(cmdbuf));
315
log_debug("link op: %p", buffer->vaddr + waitlink_offset);
316
log_debug("addr: 0x%08x", link_target);
317
log_debug("back: 0x%08x", return_target);
318
log_debug("event: %d", event);
324
etnaviv_buffer_replace_wait(buffer, waitlink_offset,
325
VIV_FE_LINK_HEADER_OP_LINK | VIV_FE_LINK_HEADER_PREFETCH(link_dwords),
328
etnaviv_buffer_dump(gpu, buffer, 0, buffer->user_size);