1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#ifndef FREEDRENO_RINGBUFFER_H_ 28bf215546Sopenharmony_ci#define FREEDRENO_RINGBUFFER_H_ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include <stdio.h> 31bf215546Sopenharmony_ci#include "util/u_atomic.h" 32bf215546Sopenharmony_ci#include "util/u_debug.h" 33bf215546Sopenharmony_ci#include "util/u_queue.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "adreno_common.xml.h" 36bf215546Sopenharmony_ci#include "adreno_pm4.xml.h" 37bf215546Sopenharmony_ci#include "freedreno_drmif.h" 38bf215546Sopenharmony_ci#include "freedreno_pm4.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#ifdef __cplusplus 41bf215546Sopenharmony_ciextern "C" { 42bf215546Sopenharmony_ci#endif 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cistruct fd_submit; 45bf215546Sopenharmony_cistruct fd_ringbuffer; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cienum fd_ringbuffer_flags { 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci /* Primary ringbuffer for a submit, ie. an IB1 level rb 50bf215546Sopenharmony_ci * which kernel must setup RB->IB1 CP_INDIRECT_BRANCH 51bf215546Sopenharmony_ci * packets. 52bf215546Sopenharmony_ci */ 53bf215546Sopenharmony_ci FD_RINGBUFFER_PRIMARY = 0x1, 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci /* Hint that the stateobj will be used for streaming state 56bf215546Sopenharmony_ci * that is used once or a few times and then discarded. 57bf215546Sopenharmony_ci * 58bf215546Sopenharmony_ci * For sub-allocation, non streaming stateobj's should be 59bf215546Sopenharmony_ci * sub-allocated from a page size buffer, so one long lived 60bf215546Sopenharmony_ci * state obj doesn't prevent other pages from being freed. 61bf215546Sopenharmony_ci * (Ie. it would be no worse than allocating a page sized 62bf215546Sopenharmony_ci * bo for each small non-streaming stateobj). 63bf215546Sopenharmony_ci * 64bf215546Sopenharmony_ci * But streaming stateobj's could be sub-allocated from a 65bf215546Sopenharmony_ci * larger buffer to reduce the alloc/del overhead. 66bf215546Sopenharmony_ci */ 67bf215546Sopenharmony_ci FD_RINGBUFFER_STREAMING = 0x2, 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci /* Indicates that "growable" cmdstream can be used, 70bf215546Sopenharmony_ci * consisting of multiple physical cmdstream buffers 71bf215546Sopenharmony_ci */ 72bf215546Sopenharmony_ci FD_RINGBUFFER_GROWABLE = 0x4, 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci /* Internal use only: */ 75bf215546Sopenharmony_ci _FD_RINGBUFFER_OBJECT = 0x8, 76bf215546Sopenharmony_ci}; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci/* A submit object manages/tracks all the state buildup for a "submit" 79bf215546Sopenharmony_ci * ioctl to the kernel. Additionally, with the exception of long-lived 80bf215546Sopenharmony_ci * non-STREAMING stateobj rb's, rb's are allocated from the submit. 81bf215546Sopenharmony_ci */ 82bf215546Sopenharmony_cistruct fd_submit *fd_submit_new(struct fd_pipe *pipe); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci/* NOTE: all ringbuffer's create from the submit should be unref'd 85bf215546Sopenharmony_ci * before destroying the submit. 86bf215546Sopenharmony_ci */ 87bf215546Sopenharmony_civoid fd_submit_del(struct fd_submit *submit); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_cistruct fd_submit * fd_submit_ref(struct fd_submit *submit); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci/* Allocate a new rb from the submit. */ 92bf215546Sopenharmony_cistruct fd_ringbuffer *fd_submit_new_ringbuffer(struct fd_submit *submit, 93bf215546Sopenharmony_ci uint32_t size, 94bf215546Sopenharmony_ci enum fd_ringbuffer_flags flags); 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci/** 97bf215546Sopenharmony_ci * Encapsulates submit out-fence(s), which consist of a 'timestamp' (per- 98bf215546Sopenharmony_ci * pipe (submitqueue) sequence number) and optionally, if requested, an 99bf215546Sopenharmony_ci * out-fence-fd 100bf215546Sopenharmony_ci */ 101bf215546Sopenharmony_cistruct fd_submit_fence { 102bf215546Sopenharmony_ci /** 103bf215546Sopenharmony_ci * The ready fence is signaled once the submit is actually flushed down 104bf215546Sopenharmony_ci * to the kernel, and fence/fence_fd are populated. You must wait for 105bf215546Sopenharmony_ci * this fence to be signaled before reading fence/fence_fd. 106bf215546Sopenharmony_ci */ 107bf215546Sopenharmony_ci struct util_queue_fence ready; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci struct fd_fence fence; 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci /** 112bf215546Sopenharmony_ci * Optional dma_fence fd, returned by submit if use_fence_fd is true 113bf215546Sopenharmony_ci */ 114bf215546Sopenharmony_ci int fence_fd; 115bf215546Sopenharmony_ci bool use_fence_fd; 116bf215546Sopenharmony_ci}; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci/* in_fence_fd: -1 for no in-fence, else fence fd 119bf215546Sopenharmony_ci * out_fence can be NULL if no output fence is required 120bf215546Sopenharmony_ci */ 121bf215546Sopenharmony_ciint fd_submit_flush(struct fd_submit *submit, int in_fence_fd, 122bf215546Sopenharmony_ci struct fd_submit_fence *out_fence); 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_cistruct fd_ringbuffer; 125bf215546Sopenharmony_cistruct fd_reloc; 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_cistruct fd_ringbuffer_funcs { 128bf215546Sopenharmony_ci void (*grow)(struct fd_ringbuffer *ring, uint32_t size); 129bf215546Sopenharmony_ci void (*emit_reloc)(struct fd_ringbuffer *ring, const struct fd_reloc *reloc); 130bf215546Sopenharmony_ci uint32_t (*emit_reloc_ring)(struct fd_ringbuffer *ring, 131bf215546Sopenharmony_ci struct fd_ringbuffer *target, uint32_t cmd_idx); 132bf215546Sopenharmony_ci uint32_t (*cmd_count)(struct fd_ringbuffer *ring); 133bf215546Sopenharmony_ci bool (*check_size)(struct fd_ringbuffer *ring); 134bf215546Sopenharmony_ci void (*destroy)(struct fd_ringbuffer *ring); 135bf215546Sopenharmony_ci}; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci/* the ringbuffer object is not opaque so that OUT_RING() type stuff 138bf215546Sopenharmony_ci * can be inlined. Note that users should not make assumptions about 139bf215546Sopenharmony_ci * the size of this struct. 140bf215546Sopenharmony_ci */ 141bf215546Sopenharmony_cistruct fd_ringbuffer { 142bf215546Sopenharmony_ci uint32_t *cur, *end, *start; 143bf215546Sopenharmony_ci const struct fd_ringbuffer_funcs *funcs; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci // size or end coudl probably go away 146bf215546Sopenharmony_ci int size; 147bf215546Sopenharmony_ci int32_t refcnt; 148bf215546Sopenharmony_ci enum fd_ringbuffer_flags flags; 149bf215546Sopenharmony_ci}; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci/* Allocate a new long-lived state object, not associated with 152bf215546Sopenharmony_ci * a submit: 153bf215546Sopenharmony_ci */ 154bf215546Sopenharmony_cistruct fd_ringbuffer *fd_ringbuffer_new_object(struct fd_pipe *pipe, 155bf215546Sopenharmony_ci uint32_t size); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_cistatic inline void 158bf215546Sopenharmony_cifd_ringbuffer_del(struct fd_ringbuffer *ring) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci if (!p_atomic_dec_zero(&ring->refcnt)) 161bf215546Sopenharmony_ci return; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci ring->funcs->destroy(ring); 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_cistatic inline struct fd_ringbuffer * 167bf215546Sopenharmony_cifd_ringbuffer_ref(struct fd_ringbuffer *ring) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci p_atomic_inc(&ring->refcnt); 170bf215546Sopenharmony_ci return ring; 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_cistatic inline void 174bf215546Sopenharmony_cifd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci assert(ring->funcs->grow); /* unsupported on kgsl */ 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci /* there is an upper bound on IB size, which appears to be 0x0fffff */ 179bf215546Sopenharmony_ci ring->size = MIN2(ring->size << 1, 0x0fffff); 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci ring->funcs->grow(ring, ring->size); 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_cistatic inline bool 185bf215546Sopenharmony_cifd_ringbuffer_check_size(struct fd_ringbuffer *ring) 186bf215546Sopenharmony_ci{ 187bf215546Sopenharmony_ci return ring->funcs->check_size(ring); 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic inline void 191bf215546Sopenharmony_cifd_ringbuffer_emit(struct fd_ringbuffer *ring, uint32_t data) 192bf215546Sopenharmony_ci{ 193bf215546Sopenharmony_ci (*ring->cur++) = data; 194bf215546Sopenharmony_ci} 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_cistruct fd_reloc { 197bf215546Sopenharmony_ci struct fd_bo *bo; 198bf215546Sopenharmony_ci uint64_t iova; 199bf215546Sopenharmony_ci uint64_t orval; 200bf215546Sopenharmony_ci#define FD_RELOC_READ 0x0001 201bf215546Sopenharmony_ci#define FD_RELOC_WRITE 0x0002 202bf215546Sopenharmony_ci#define FD_RELOC_DUMP 0x0004 203bf215546Sopenharmony_ci uint32_t offset; 204bf215546Sopenharmony_ci int32_t shift; 205bf215546Sopenharmony_ci}; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci/* We always mark BOs for write, instead of tracking it across reloc 208bf215546Sopenharmony_ci * sources in userspace. On the kernel side, this means we track a single 209bf215546Sopenharmony_ci * excl fence in the BO instead of a set of read fences, which is cheaper. 210bf215546Sopenharmony_ci * The downside is that a dmabuf-shared device won't be able to read in 211bf215546Sopenharmony_ci * parallel with a read-only access by freedreno, but most other drivers 212bf215546Sopenharmony_ci * have decided that that usecase isn't important enough to do this 213bf215546Sopenharmony_ci * tracking, as well. 214bf215546Sopenharmony_ci */ 215bf215546Sopenharmony_ci#define FD_RELOC_FLAGS_INIT (FD_RELOC_READ | FD_RELOC_WRITE) 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci/* NOTE: relocs are 2 dwords on a5xx+ */ 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_cistatic inline void 220bf215546Sopenharmony_cifd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc) 221bf215546Sopenharmony_ci{ 222bf215546Sopenharmony_ci ring->funcs->emit_reloc(ring, reloc); 223bf215546Sopenharmony_ci} 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_cistatic inline uint32_t 226bf215546Sopenharmony_cifd_ringbuffer_cmd_count(struct fd_ringbuffer *ring) 227bf215546Sopenharmony_ci{ 228bf215546Sopenharmony_ci if (!ring->funcs->cmd_count) 229bf215546Sopenharmony_ci return 1; 230bf215546Sopenharmony_ci return ring->funcs->cmd_count(ring); 231bf215546Sopenharmony_ci} 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_cistatic inline uint32_t 234bf215546Sopenharmony_cifd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, 235bf215546Sopenharmony_ci struct fd_ringbuffer *target, 236bf215546Sopenharmony_ci uint32_t cmd_idx) 237bf215546Sopenharmony_ci{ 238bf215546Sopenharmony_ci return ring->funcs->emit_reloc_ring(ring, target, cmd_idx); 239bf215546Sopenharmony_ci} 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_cistatic inline uint32_t 242bf215546Sopenharmony_cioffset_bytes(void *end, void *start) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci return ((char *)end) - ((char *)start); 245bf215546Sopenharmony_ci} 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_cistatic inline uint32_t 248bf215546Sopenharmony_cifd_ringbuffer_size(struct fd_ringbuffer *ring) 249bf215546Sopenharmony_ci{ 250bf215546Sopenharmony_ci /* only really needed for stateobj ringbuffers, and won't really 251bf215546Sopenharmony_ci * do what you expect for growable rb's.. so lets just restrict 252bf215546Sopenharmony_ci * this to stateobj's for now: 253bf215546Sopenharmony_ci */ 254bf215546Sopenharmony_ci assert(!(ring->flags & FD_RINGBUFFER_GROWABLE)); 255bf215546Sopenharmony_ci return offset_bytes(ring->cur, ring->start); 256bf215546Sopenharmony_ci} 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_cistatic inline bool 259bf215546Sopenharmony_cifd_ringbuffer_empty(struct fd_ringbuffer *ring) 260bf215546Sopenharmony_ci{ 261bf215546Sopenharmony_ci return (fd_ringbuffer_cmd_count(ring) == 1) && 262bf215546Sopenharmony_ci (offset_bytes(ring->cur, ring->start) == 0); 263bf215546Sopenharmony_ci} 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci#define LOG_DWORDS 0 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_cistatic inline void 268bf215546Sopenharmony_ciOUT_RING(struct fd_ringbuffer *ring, uint32_t data) 269bf215546Sopenharmony_ci{ 270bf215546Sopenharmony_ci if (LOG_DWORDS) { 271bf215546Sopenharmony_ci fprintf(stderr, "ring[%p]: OUT_RING %04x: %08x", ring, 272bf215546Sopenharmony_ci (uint32_t)(ring->cur - ring->start), data); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci fd_ringbuffer_emit(ring, data); 275bf215546Sopenharmony_ci} 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci/* 278bf215546Sopenharmony_ci * NOTE: OUT_RELOC() is 2 dwords (64b) on a5xx+ 279bf215546Sopenharmony_ci */ 280bf215546Sopenharmony_cistatic inline void 281bf215546Sopenharmony_ciOUT_RELOC(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t offset, 282bf215546Sopenharmony_ci uint64_t orval, int32_t shift) 283bf215546Sopenharmony_ci{ 284bf215546Sopenharmony_ci if (LOG_DWORDS) { 285bf215546Sopenharmony_ci fprintf(stderr, "ring[%p]: OUT_RELOC %04x: %p+%u << %d", ring, 286bf215546Sopenharmony_ci (uint32_t)(ring->cur - ring->start), bo, offset, shift); 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci assert(offset < fd_bo_size(bo)); 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci uint64_t iova = fd_bo_get_iova(bo) + offset; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci if (shift < 0) 293bf215546Sopenharmony_ci iova >>= -shift; 294bf215546Sopenharmony_ci else 295bf215546Sopenharmony_ci iova <<= shift; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci iova |= orval; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci struct fd_reloc reloc = { 300bf215546Sopenharmony_ci .bo = bo, 301bf215546Sopenharmony_ci .iova = iova, 302bf215546Sopenharmony_ci .orval = orval, 303bf215546Sopenharmony_ci .offset = offset, 304bf215546Sopenharmony_ci .shift = shift, 305bf215546Sopenharmony_ci }; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci fd_ringbuffer_reloc(ring, &reloc); 308bf215546Sopenharmony_ci} 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_cistatic inline void 311bf215546Sopenharmony_ciOUT_RB(struct fd_ringbuffer *ring, struct fd_ringbuffer *target) 312bf215546Sopenharmony_ci{ 313bf215546Sopenharmony_ci fd_ringbuffer_emit_reloc_ring_full(ring, target, 0); 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_cistatic inline void 317bf215546Sopenharmony_ciBEGIN_RING(struct fd_ringbuffer *ring, uint32_t ndwords) 318bf215546Sopenharmony_ci{ 319bf215546Sopenharmony_ci if (unlikely(ring->cur + ndwords > ring->end)) 320bf215546Sopenharmony_ci fd_ringbuffer_grow(ring, ndwords); 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_cistatic inline void 324bf215546Sopenharmony_ciOUT_PKT0(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci BEGIN_RING(ring, cnt + 1); 327bf215546Sopenharmony_ci OUT_RING(ring, pm4_pkt0_hdr(regindx, cnt)); 328bf215546Sopenharmony_ci} 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_cistatic inline void 331bf215546Sopenharmony_ciOUT_PKT2(struct fd_ringbuffer *ring) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci BEGIN_RING(ring, 1); 334bf215546Sopenharmony_ci OUT_RING(ring, CP_TYPE2_PKT); 335bf215546Sopenharmony_ci} 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_cistatic inline void 338bf215546Sopenharmony_ciOUT_PKT3(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt) 339bf215546Sopenharmony_ci{ 340bf215546Sopenharmony_ci BEGIN_RING(ring, cnt + 1); 341bf215546Sopenharmony_ci OUT_RING(ring, CP_TYPE3_PKT | ((cnt - 1) << 16) | ((opcode & 0xFF) << 8)); 342bf215546Sopenharmony_ci} 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci/* 345bf215546Sopenharmony_ci * Starting with a5xx, pkt4/pkt7 are used instead of pkt0/pkt3 346bf215546Sopenharmony_ci */ 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_cistatic inline void 349bf215546Sopenharmony_ciOUT_PKT4(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt) 350bf215546Sopenharmony_ci{ 351bf215546Sopenharmony_ci BEGIN_RING(ring, cnt + 1); 352bf215546Sopenharmony_ci OUT_RING(ring, pm4_pkt4_hdr(regindx, cnt)); 353bf215546Sopenharmony_ci} 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_cistatic inline void 356bf215546Sopenharmony_ciOUT_PKT7(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt) 357bf215546Sopenharmony_ci{ 358bf215546Sopenharmony_ci BEGIN_RING(ring, cnt + 1); 359bf215546Sopenharmony_ci OUT_RING(ring, pm4_pkt7_hdr(opcode, cnt)); 360bf215546Sopenharmony_ci} 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_cistatic inline void 363bf215546Sopenharmony_ciOUT_WFI(struct fd_ringbuffer *ring) 364bf215546Sopenharmony_ci{ 365bf215546Sopenharmony_ci OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); 366bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 367bf215546Sopenharmony_ci} 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_cistatic inline void 370bf215546Sopenharmony_ciOUT_WFI5(struct fd_ringbuffer *ring) 371bf215546Sopenharmony_ci{ 372bf215546Sopenharmony_ci OUT_PKT7(ring, CP_WAIT_FOR_IDLE, 0); 373bf215546Sopenharmony_ci} 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci#ifdef __cplusplus 376bf215546Sopenharmony_ci} /* end of extern "C" */ 377bf215546Sopenharmony_ci#endif 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci#endif /* FREEDRENO_RINGBUFFER_H_ */ 380