xref: /aosp_15_r20/external/mesa3d/src/freedreno/drm/freedreno_ringbuffer.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2012-2018 Rob Clark <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * Authors:
6*61046927SAndroid Build Coastguard Worker  *    Rob Clark <[email protected]>
7*61046927SAndroid Build Coastguard Worker  */
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #ifndef FREEDRENO_RINGBUFFER_H_
10*61046927SAndroid Build Coastguard Worker #define FREEDRENO_RINGBUFFER_H_
11*61046927SAndroid Build Coastguard Worker 
12*61046927SAndroid Build Coastguard Worker #include <stdio.h>
13*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
14*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker #include "adreno_common.xml.h"
17*61046927SAndroid Build Coastguard Worker #include "adreno_pm4.xml.h"
18*61046927SAndroid Build Coastguard Worker #include "freedreno_drmif.h"
19*61046927SAndroid Build Coastguard Worker #include "freedreno_pm4.h"
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
22*61046927SAndroid Build Coastguard Worker extern "C" {
23*61046927SAndroid Build Coastguard Worker #endif
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker struct fd_submit;
26*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer;
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker enum fd_ringbuffer_flags {
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker    /* Primary ringbuffer for a submit, ie. an IB1 level rb
31*61046927SAndroid Build Coastguard Worker     * which kernel must setup RB->IB1 CP_INDIRECT_BRANCH
32*61046927SAndroid Build Coastguard Worker     * packets.
33*61046927SAndroid Build Coastguard Worker     */
34*61046927SAndroid Build Coastguard Worker    FD_RINGBUFFER_PRIMARY = 0x1,
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker    /* Hint that the stateobj will be used for streaming state
37*61046927SAndroid Build Coastguard Worker     * that is used once or a few times and then discarded.
38*61046927SAndroid Build Coastguard Worker     *
39*61046927SAndroid Build Coastguard Worker     * For sub-allocation, non streaming stateobj's should be
40*61046927SAndroid Build Coastguard Worker     * sub-allocated from a page size buffer, so one long lived
41*61046927SAndroid Build Coastguard Worker     * state obj doesn't prevent other pages from being freed.
42*61046927SAndroid Build Coastguard Worker     * (Ie. it would be no worse than allocating a page sized
43*61046927SAndroid Build Coastguard Worker     * bo for each small non-streaming stateobj).
44*61046927SAndroid Build Coastguard Worker     *
45*61046927SAndroid Build Coastguard Worker     * But streaming stateobj's could be sub-allocated from a
46*61046927SAndroid Build Coastguard Worker     * larger buffer to reduce the alloc/del overhead.
47*61046927SAndroid Build Coastguard Worker     */
48*61046927SAndroid Build Coastguard Worker    FD_RINGBUFFER_STREAMING = 0x2,
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker    /* Indicates that "growable" cmdstream can be used,
51*61046927SAndroid Build Coastguard Worker     * consisting of multiple physical cmdstream buffers
52*61046927SAndroid Build Coastguard Worker     */
53*61046927SAndroid Build Coastguard Worker    FD_RINGBUFFER_GROWABLE = 0x4,
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker    /* Internal use only: */
56*61046927SAndroid Build Coastguard Worker    _FD_RINGBUFFER_OBJECT = 0x8,
57*61046927SAndroid Build Coastguard Worker };
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker /* A submit object manages/tracks all the state buildup for a "submit"
60*61046927SAndroid Build Coastguard Worker  * ioctl to the kernel.  Additionally, with the exception of long-lived
61*61046927SAndroid Build Coastguard Worker  * non-STREAMING stateobj rb's, rb's are allocated from the submit.
62*61046927SAndroid Build Coastguard Worker  */
63*61046927SAndroid Build Coastguard Worker struct fd_submit *fd_submit_new(struct fd_pipe *pipe);
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker /* NOTE: all ringbuffer's create from the submit should be unref'd
66*61046927SAndroid Build Coastguard Worker  * before destroying the submit.
67*61046927SAndroid Build Coastguard Worker  */
68*61046927SAndroid Build Coastguard Worker void fd_submit_del(struct fd_submit *submit);
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker struct fd_submit * fd_submit_ref(struct fd_submit *submit);
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker /* Allocate a new rb from the submit. */
73*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer *fd_submit_new_ringbuffer(struct fd_submit *submit,
74*61046927SAndroid Build Coastguard Worker                                                uint32_t size,
75*61046927SAndroid Build Coastguard Worker                                                enum fd_ringbuffer_flags flags);
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker /* in_fence_fd: -1 for no in-fence, else fence fd
78*61046927SAndroid Build Coastguard Worker  * if use_fence_fd is true the output fence will be dma_fence fd backed
79*61046927SAndroid Build Coastguard Worker  */
80*61046927SAndroid Build Coastguard Worker struct fd_fence *fd_submit_flush(struct fd_submit *submit, int in_fence_fd,
81*61046927SAndroid Build Coastguard Worker                                  bool use_fence_fd);
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer;
84*61046927SAndroid Build Coastguard Worker struct fd_reloc;
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer_funcs {
87*61046927SAndroid Build Coastguard Worker    void (*grow)(struct fd_ringbuffer *ring, uint32_t size);
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    /**
90*61046927SAndroid Build Coastguard Worker     * Alternative to emit_reloc for the softpin case, where we only need
91*61046927SAndroid Build Coastguard Worker     * to track that the bo is used (and not track all the extra info that
92*61046927SAndroid Build Coastguard Worker     * the kernel would need to do a legacy reloc.
93*61046927SAndroid Build Coastguard Worker     */
94*61046927SAndroid Build Coastguard Worker    void (*emit_bo)(struct fd_ringbuffer *ring, struct fd_bo *bo);
95*61046927SAndroid Build Coastguard Worker    void (*assert_attached)(struct fd_ringbuffer *ring, struct fd_bo *bo);
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    void (*emit_reloc)(struct fd_ringbuffer *ring, const struct fd_reloc *reloc);
98*61046927SAndroid Build Coastguard Worker    uint32_t (*emit_reloc_ring)(struct fd_ringbuffer *ring,
99*61046927SAndroid Build Coastguard Worker                                struct fd_ringbuffer *target, uint32_t cmd_idx);
100*61046927SAndroid Build Coastguard Worker    uint32_t (*cmd_count)(struct fd_ringbuffer *ring);
101*61046927SAndroid Build Coastguard Worker    bool (*check_size)(struct fd_ringbuffer *ring);
102*61046927SAndroid Build Coastguard Worker    void (*destroy)(struct fd_ringbuffer *ring);
103*61046927SAndroid Build Coastguard Worker };
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker /* the ringbuffer object is not opaque so that OUT_RING() type stuff
106*61046927SAndroid Build Coastguard Worker  * can be inlined.  Note that users should not make assumptions about
107*61046927SAndroid Build Coastguard Worker  * the size of this struct.
108*61046927SAndroid Build Coastguard Worker  */
109*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer {
110*61046927SAndroid Build Coastguard Worker    uint32_t *cur, *end, *start;
111*61046927SAndroid Build Coastguard Worker    const struct fd_ringbuffer_funcs *funcs;
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    // size or end coudl probably go away
114*61046927SAndroid Build Coastguard Worker    int size;
115*61046927SAndroid Build Coastguard Worker    int32_t refcnt;
116*61046927SAndroid Build Coastguard Worker    enum fd_ringbuffer_flags flags;
117*61046927SAndroid Build Coastguard Worker };
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker /* Allocate a new long-lived state object, not associated with
120*61046927SAndroid Build Coastguard Worker  * a submit:
121*61046927SAndroid Build Coastguard Worker  */
122*61046927SAndroid Build Coastguard Worker struct fd_ringbuffer *fd_ringbuffer_new_object(struct fd_pipe *pipe,
123*61046927SAndroid Build Coastguard Worker                                                uint32_t size);
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker /*
126*61046927SAndroid Build Coastguard Worker  * Helpers for ref/unref with some extra debugging.. unref() returns true if
127*61046927SAndroid Build Coastguard Worker  * the object is still live
128*61046927SAndroid Build Coastguard Worker  */
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker static inline void
ref(int32_t * ref)131*61046927SAndroid Build Coastguard Worker ref(int32_t *ref)
132*61046927SAndroid Build Coastguard Worker {
133*61046927SAndroid Build Coastguard Worker    ASSERTED int32_t count = p_atomic_inc_return(ref);
134*61046927SAndroid Build Coastguard Worker    /* We should never see a refcnt transition 0->1, this is a sign of a
135*61046927SAndroid Build Coastguard Worker     * zombie coming back from the dead!
136*61046927SAndroid Build Coastguard Worker     */
137*61046927SAndroid Build Coastguard Worker    assert(count != 1);
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker static inline bool
unref(int32_t * ref)141*61046927SAndroid Build Coastguard Worker unref(int32_t *ref)
142*61046927SAndroid Build Coastguard Worker {
143*61046927SAndroid Build Coastguard Worker    int32_t count = p_atomic_dec_return(ref);
144*61046927SAndroid Build Coastguard Worker    assert(count != -1);
145*61046927SAndroid Build Coastguard Worker    return count == 0;
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_del(struct fd_ringbuffer * ring)149*61046927SAndroid Build Coastguard Worker fd_ringbuffer_del(struct fd_ringbuffer *ring)
150*61046927SAndroid Build Coastguard Worker {
151*61046927SAndroid Build Coastguard Worker    if (--ring->refcnt > 0)
152*61046927SAndroid Build Coastguard Worker       return;
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker    ring->funcs->destroy(ring);
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker static inline struct fd_ringbuffer *
fd_ringbuffer_ref(struct fd_ringbuffer * ring)158*61046927SAndroid Build Coastguard Worker fd_ringbuffer_ref(struct fd_ringbuffer *ring)
159*61046927SAndroid Build Coastguard Worker {
160*61046927SAndroid Build Coastguard Worker    ring->refcnt++;
161*61046927SAndroid Build Coastguard Worker    return ring;
162*61046927SAndroid Build Coastguard Worker }
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_grow(struct fd_ringbuffer * ring,uint32_t ndwords)165*61046927SAndroid Build Coastguard Worker fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords)
166*61046927SAndroid Build Coastguard Worker {
167*61046927SAndroid Build Coastguard Worker    assert(ring->funcs->grow); /* unsupported on kgsl */
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    ring->funcs->grow(ring, ring->size);
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker static inline bool
fd_ringbuffer_check_size(struct fd_ringbuffer * ring)173*61046927SAndroid Build Coastguard Worker fd_ringbuffer_check_size(struct fd_ringbuffer *ring)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker    return ring->funcs->check_size(ring);
176*61046927SAndroid Build Coastguard Worker }
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_emit(struct fd_ringbuffer * ring,uint32_t data)179*61046927SAndroid Build Coastguard Worker fd_ringbuffer_emit(struct fd_ringbuffer *ring, uint32_t data)
180*61046927SAndroid Build Coastguard Worker {
181*61046927SAndroid Build Coastguard Worker    (*ring->cur++) = data;
182*61046927SAndroid Build Coastguard Worker }
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker struct fd_reloc {
185*61046927SAndroid Build Coastguard Worker    struct fd_bo *bo;
186*61046927SAndroid Build Coastguard Worker    uint64_t iova;
187*61046927SAndroid Build Coastguard Worker    uint64_t orval;
188*61046927SAndroid Build Coastguard Worker #define FD_RELOC_READ  0x0001
189*61046927SAndroid Build Coastguard Worker #define FD_RELOC_WRITE 0x0002
190*61046927SAndroid Build Coastguard Worker #define FD_RELOC_DUMP  0x0004
191*61046927SAndroid Build Coastguard Worker    uint32_t offset;
192*61046927SAndroid Build Coastguard Worker    int32_t shift;
193*61046927SAndroid Build Coastguard Worker };
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker /* We always mark BOs for write, instead of tracking it across reloc
196*61046927SAndroid Build Coastguard Worker  * sources in userspace.  On the kernel side, this means we track a single
197*61046927SAndroid Build Coastguard Worker  * excl fence in the BO instead of a set of read fences, which is cheaper.
198*61046927SAndroid Build Coastguard Worker  * The downside is that a dmabuf-shared device won't be able to read in
199*61046927SAndroid Build Coastguard Worker  * parallel with a read-only access by freedreno, but most other drivers
200*61046927SAndroid Build Coastguard Worker  * have decided that that usecase isn't important enough to do this
201*61046927SAndroid Build Coastguard Worker  * tracking, as well.
202*61046927SAndroid Build Coastguard Worker  */
203*61046927SAndroid Build Coastguard Worker #define FD_RELOC_FLAGS_INIT (FD_RELOC_READ | FD_RELOC_WRITE)
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker /* NOTE: relocs are 2 dwords on a5xx+ */
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_attach_bo(struct fd_ringbuffer * ring,struct fd_bo * bo)208*61046927SAndroid Build Coastguard Worker fd_ringbuffer_attach_bo(struct fd_ringbuffer *ring, struct fd_bo *bo)
209*61046927SAndroid Build Coastguard Worker {
210*61046927SAndroid Build Coastguard Worker    ring->funcs->emit_bo(ring, bo);
211*61046927SAndroid Build Coastguard Worker }
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_assert_attached(struct fd_ringbuffer * ring,struct fd_bo * bo)214*61046927SAndroid Build Coastguard Worker fd_ringbuffer_assert_attached(struct fd_ringbuffer *ring, struct fd_bo *bo)
215*61046927SAndroid Build Coastguard Worker {
216*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
217*61046927SAndroid Build Coastguard Worker    ring->funcs->assert_attached(ring, bo);
218*61046927SAndroid Build Coastguard Worker #endif
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker static inline void
fd_ringbuffer_reloc(struct fd_ringbuffer * ring,const struct fd_reloc * reloc)222*61046927SAndroid Build Coastguard Worker fd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc)
223*61046927SAndroid Build Coastguard Worker {
224*61046927SAndroid Build Coastguard Worker    ring->funcs->emit_reloc(ring, reloc);
225*61046927SAndroid Build Coastguard Worker }
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker static inline uint32_t
fd_ringbuffer_cmd_count(struct fd_ringbuffer * ring)228*61046927SAndroid Build Coastguard Worker fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
229*61046927SAndroid Build Coastguard Worker {
230*61046927SAndroid Build Coastguard Worker    if (!ring->funcs->cmd_count)
231*61046927SAndroid Build Coastguard Worker       return 1;
232*61046927SAndroid Build Coastguard Worker    return ring->funcs->cmd_count(ring);
233*61046927SAndroid Build Coastguard Worker }
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker static inline uint32_t
fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer * ring,struct fd_ringbuffer * target,uint32_t cmd_idx)236*61046927SAndroid Build Coastguard Worker fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring,
237*61046927SAndroid Build Coastguard Worker                                    struct fd_ringbuffer *target,
238*61046927SAndroid Build Coastguard Worker                                    uint32_t cmd_idx)
239*61046927SAndroid Build Coastguard Worker {
240*61046927SAndroid Build Coastguard Worker    return ring->funcs->emit_reloc_ring(ring, target, cmd_idx);
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker static inline uint32_t
offset_bytes(void * end,void * start)244*61046927SAndroid Build Coastguard Worker offset_bytes(void *end, void *start)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker    return ((char *)end) - ((char *)start);
247*61046927SAndroid Build Coastguard Worker }
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker static inline uint32_t
fd_ringbuffer_size(struct fd_ringbuffer * ring)250*61046927SAndroid Build Coastguard Worker fd_ringbuffer_size(struct fd_ringbuffer *ring)
251*61046927SAndroid Build Coastguard Worker {
252*61046927SAndroid Build Coastguard Worker    /* only really needed for stateobj ringbuffers, and won't really
253*61046927SAndroid Build Coastguard Worker     * do what you expect for growable rb's.. so lets just restrict
254*61046927SAndroid Build Coastguard Worker     * this to stateobj's for now:
255*61046927SAndroid Build Coastguard Worker     */
256*61046927SAndroid Build Coastguard Worker    assert(!(ring->flags & FD_RINGBUFFER_GROWABLE));
257*61046927SAndroid Build Coastguard Worker    return offset_bytes(ring->cur, ring->start);
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker static inline bool
fd_ringbuffer_empty(struct fd_ringbuffer * ring)261*61046927SAndroid Build Coastguard Worker fd_ringbuffer_empty(struct fd_ringbuffer *ring)
262*61046927SAndroid Build Coastguard Worker {
263*61046927SAndroid Build Coastguard Worker    return (fd_ringbuffer_cmd_count(ring) == 1) &&
264*61046927SAndroid Build Coastguard Worker           (offset_bytes(ring->cur, ring->start) == 0);
265*61046927SAndroid Build Coastguard Worker }
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker #define LOG_DWORDS 0
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker static inline void
OUT_RING(struct fd_ringbuffer * ring,uint32_t data)270*61046927SAndroid Build Coastguard Worker OUT_RING(struct fd_ringbuffer *ring, uint32_t data)
271*61046927SAndroid Build Coastguard Worker {
272*61046927SAndroid Build Coastguard Worker    if (LOG_DWORDS) {
273*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "ring[%p]: OUT_RING   %04x:  %08x", ring,
274*61046927SAndroid Build Coastguard Worker               (uint32_t)(ring->cur - ring->start), data);
275*61046927SAndroid Build Coastguard Worker    }
276*61046927SAndroid Build Coastguard Worker    fd_ringbuffer_emit(ring, data);
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker static inline uint64_t
__reloc_iova(struct fd_bo * bo,uint32_t offset,uint64_t orval,int32_t shift)280*61046927SAndroid Build Coastguard Worker __reloc_iova(struct fd_bo *bo, uint32_t offset, uint64_t orval, int32_t shift)
281*61046927SAndroid Build Coastguard Worker {
282*61046927SAndroid Build Coastguard Worker    uint64_t iova = fd_bo_get_iova(bo) + offset;
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker    if (shift < 0)
285*61046927SAndroid Build Coastguard Worker       iova >>= -shift;
286*61046927SAndroid Build Coastguard Worker    else
287*61046927SAndroid Build Coastguard Worker       iova <<= shift;
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    iova |= orval;
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    return iova;
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker /*
295*61046927SAndroid Build Coastguard Worker  * NOTE: OUT_RELOC() is 2 dwords (64b) on a5xx+
296*61046927SAndroid Build Coastguard Worker  */
297*61046927SAndroid Build Coastguard Worker static inline void
OUT_RELOC(struct fd_ringbuffer * ring,struct fd_bo * bo,uint32_t offset,uint64_t orval,int32_t shift)298*61046927SAndroid Build Coastguard Worker OUT_RELOC(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t offset,
299*61046927SAndroid Build Coastguard Worker           uint64_t orval, int32_t shift)
300*61046927SAndroid Build Coastguard Worker {
301*61046927SAndroid Build Coastguard Worker    if (LOG_DWORDS) {
302*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "ring[%p]: OUT_RELOC   %04x:  %p+%u << %d", ring,
303*61046927SAndroid Build Coastguard Worker               (uint32_t)(ring->cur - ring->start), bo, offset, shift);
304*61046927SAndroid Build Coastguard Worker    }
305*61046927SAndroid Build Coastguard Worker    assert(offset < fd_bo_size(bo));
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker    uint64_t iova = __reloc_iova(bo, offset, orval, shift);
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker #if FD_BO_NO_HARDPIN
310*61046927SAndroid Build Coastguard Worker    uint64_t *cur = (uint64_t *)ring->cur;
311*61046927SAndroid Build Coastguard Worker    *cur = iova;
312*61046927SAndroid Build Coastguard Worker    ring->cur += 2;
313*61046927SAndroid Build Coastguard Worker    fd_ringbuffer_assert_attached(ring, bo);
314*61046927SAndroid Build Coastguard Worker #else
315*61046927SAndroid Build Coastguard Worker    struct fd_reloc reloc = {
316*61046927SAndroid Build Coastguard Worker          .bo = bo,
317*61046927SAndroid Build Coastguard Worker          .iova = iova,
318*61046927SAndroid Build Coastguard Worker          .orval = orval,
319*61046927SAndroid Build Coastguard Worker          .offset = offset,
320*61046927SAndroid Build Coastguard Worker          .shift = shift,
321*61046927SAndroid Build Coastguard Worker    };
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    fd_ringbuffer_reloc(ring, &reloc);
324*61046927SAndroid Build Coastguard Worker #endif
325*61046927SAndroid Build Coastguard Worker }
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker static inline void
OUT_RB(struct fd_ringbuffer * ring,struct fd_ringbuffer * target)328*61046927SAndroid Build Coastguard Worker OUT_RB(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
329*61046927SAndroid Build Coastguard Worker {
330*61046927SAndroid Build Coastguard Worker    fd_ringbuffer_emit_reloc_ring_full(ring, target, 0);
331*61046927SAndroid Build Coastguard Worker }
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker static inline void
BEGIN_RING(struct fd_ringbuffer * ring,uint32_t ndwords)334*61046927SAndroid Build Coastguard Worker BEGIN_RING(struct fd_ringbuffer *ring, uint32_t ndwords)
335*61046927SAndroid Build Coastguard Worker {
336*61046927SAndroid Build Coastguard Worker    if (unlikely(ring->cur + ndwords > ring->end))
337*61046927SAndroid Build Coastguard Worker       fd_ringbuffer_grow(ring, ndwords);
338*61046927SAndroid Build Coastguard Worker }
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT0(struct fd_ringbuffer * ring,uint16_t regindx,uint16_t cnt)341*61046927SAndroid Build Coastguard Worker OUT_PKT0(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
342*61046927SAndroid Build Coastguard Worker {
343*61046927SAndroid Build Coastguard Worker    BEGIN_RING(ring, cnt + 1);
344*61046927SAndroid Build Coastguard Worker    OUT_RING(ring, pm4_pkt0_hdr(regindx, cnt));
345*61046927SAndroid Build Coastguard Worker }
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT2(struct fd_ringbuffer * ring)348*61046927SAndroid Build Coastguard Worker OUT_PKT2(struct fd_ringbuffer *ring)
349*61046927SAndroid Build Coastguard Worker {
350*61046927SAndroid Build Coastguard Worker    BEGIN_RING(ring, 1);
351*61046927SAndroid Build Coastguard Worker    OUT_RING(ring, CP_TYPE2_PKT);
352*61046927SAndroid Build Coastguard Worker }
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT3(struct fd_ringbuffer * ring,uint8_t opcode,uint16_t cnt)355*61046927SAndroid Build Coastguard Worker OUT_PKT3(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
356*61046927SAndroid Build Coastguard Worker {
357*61046927SAndroid Build Coastguard Worker    BEGIN_RING(ring, cnt + 1);
358*61046927SAndroid Build Coastguard Worker    OUT_RING(ring, CP_TYPE3_PKT | ((cnt - 1) << 16) | ((opcode & 0xFF) << 8));
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker /*
362*61046927SAndroid Build Coastguard Worker  * Starting with a5xx, pkt4/pkt7 are used instead of pkt0/pkt3
363*61046927SAndroid Build Coastguard Worker  */
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT4(struct fd_ringbuffer * ring,uint16_t regindx,uint16_t cnt)366*61046927SAndroid Build Coastguard Worker OUT_PKT4(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
367*61046927SAndroid Build Coastguard Worker {
368*61046927SAndroid Build Coastguard Worker    BEGIN_RING(ring, cnt + 1);
369*61046927SAndroid Build Coastguard Worker    OUT_RING(ring, pm4_pkt4_hdr((uint16_t)regindx, (uint16_t)cnt));
370*61046927SAndroid Build Coastguard Worker }
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker static inline void
OUT_PKT7(struct fd_ringbuffer * ring,uint32_t opcode,uint32_t cnt)373*61046927SAndroid Build Coastguard Worker OUT_PKT7(struct fd_ringbuffer *ring, uint32_t opcode, uint32_t cnt)
374*61046927SAndroid Build Coastguard Worker {
375*61046927SAndroid Build Coastguard Worker    BEGIN_RING(ring, cnt + 1);
376*61046927SAndroid Build Coastguard Worker    OUT_RING(ring, pm4_pkt7_hdr((uint8_t)opcode, (uint16_t)cnt));
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker static inline void
OUT_WFI(struct fd_ringbuffer * ring)380*61046927SAndroid Build Coastguard Worker OUT_WFI(struct fd_ringbuffer *ring)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker    OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
383*61046927SAndroid Build Coastguard Worker    OUT_RING(ring, 0x00000000);
384*61046927SAndroid Build Coastguard Worker }
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker static inline void
OUT_WFI5(struct fd_ringbuffer * ring)387*61046927SAndroid Build Coastguard Worker OUT_WFI5(struct fd_ringbuffer *ring)
388*61046927SAndroid Build Coastguard Worker {
389*61046927SAndroid Build Coastguard Worker    OUT_PKT7(ring, CP_WAIT_FOR_IDLE, 0);
390*61046927SAndroid Build Coastguard Worker }
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
393*61046927SAndroid Build Coastguard Worker } /* end of extern "C" */
394*61046927SAndroid Build Coastguard Worker #endif
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker #endif /* FREEDRENO_RINGBUFFER_H_ */
397