1d722e3fbSopenharmony_ci/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2d722e3fbSopenharmony_ci 3d722e3fbSopenharmony_ci/* 4d722e3fbSopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 5d722e3fbSopenharmony_ci * 6d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation 9d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12d722e3fbSopenharmony_ci * 13d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next 14d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 15d722e3fbSopenharmony_ci * Software. 16d722e3fbSopenharmony_ci * 17d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20d722e3fbSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21d722e3fbSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22d722e3fbSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23d722e3fbSopenharmony_ci * SOFTWARE. 24d722e3fbSopenharmony_ci * 25d722e3fbSopenharmony_ci * Authors: 26d722e3fbSopenharmony_ci * Rob Clark <robclark@freedesktop.org> 27d722e3fbSopenharmony_ci */ 28d722e3fbSopenharmony_ci 29d722e3fbSopenharmony_ci#include <assert.h> 30d722e3fbSopenharmony_ci 31d722e3fbSopenharmony_ci#include "freedreno_drmif.h" 32d722e3fbSopenharmony_ci#include "freedreno_priv.h" 33d722e3fbSopenharmony_ci#include "freedreno_ringbuffer.h" 34d722e3fbSopenharmony_ci 35d722e3fbSopenharmony_cidrm_public struct fd_ringbuffer * 36d722e3fbSopenharmony_cifd_ringbuffer_new_flags(struct fd_pipe *pipe, uint32_t size, 37d722e3fbSopenharmony_ci enum fd_ringbuffer_flags flags) 38d722e3fbSopenharmony_ci{ 39d722e3fbSopenharmony_ci struct fd_ringbuffer *ring; 40d722e3fbSopenharmony_ci 41d722e3fbSopenharmony_ci /* we can't really support "growable" rb's in general for 42d722e3fbSopenharmony_ci * stateobj's since we need a single gpu addr (ie. can't 43d722e3fbSopenharmony_ci * do the trick of a chain of IB packets): 44d722e3fbSopenharmony_ci */ 45d722e3fbSopenharmony_ci if (flags & FD_RINGBUFFER_OBJECT) 46d722e3fbSopenharmony_ci assert(size); 47d722e3fbSopenharmony_ci 48d722e3fbSopenharmony_ci ring = pipe->funcs->ringbuffer_new(pipe, size, flags); 49d722e3fbSopenharmony_ci if (!ring) 50d722e3fbSopenharmony_ci return NULL; 51d722e3fbSopenharmony_ci 52d722e3fbSopenharmony_ci ring->flags = flags; 53d722e3fbSopenharmony_ci ring->pipe = pipe; 54d722e3fbSopenharmony_ci ring->start = ring->funcs->hostptr(ring); 55d722e3fbSopenharmony_ci ring->end = &(ring->start[ring->size/4]); 56d722e3fbSopenharmony_ci 57d722e3fbSopenharmony_ci ring->cur = ring->last_start = ring->start; 58d722e3fbSopenharmony_ci 59d722e3fbSopenharmony_ci return ring; 60d722e3fbSopenharmony_ci} 61d722e3fbSopenharmony_ci 62d722e3fbSopenharmony_cidrm_public struct fd_ringbuffer * 63d722e3fbSopenharmony_cifd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) 64d722e3fbSopenharmony_ci{ 65d722e3fbSopenharmony_ci return fd_ringbuffer_new_flags(pipe, size, 0); 66d722e3fbSopenharmony_ci} 67d722e3fbSopenharmony_ci 68d722e3fbSopenharmony_cidrm_public struct fd_ringbuffer * 69d722e3fbSopenharmony_cifd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size) 70d722e3fbSopenharmony_ci{ 71d722e3fbSopenharmony_ci return fd_ringbuffer_new_flags(pipe, size, FD_RINGBUFFER_OBJECT); 72d722e3fbSopenharmony_ci} 73d722e3fbSopenharmony_ci 74d722e3fbSopenharmony_cidrm_public void fd_ringbuffer_del(struct fd_ringbuffer *ring) 75d722e3fbSopenharmony_ci{ 76d722e3fbSopenharmony_ci if (!atomic_dec_and_test(&ring->refcnt)) 77d722e3fbSopenharmony_ci return; 78d722e3fbSopenharmony_ci 79d722e3fbSopenharmony_ci fd_ringbuffer_reset(ring); 80d722e3fbSopenharmony_ci ring->funcs->destroy(ring); 81d722e3fbSopenharmony_ci} 82d722e3fbSopenharmony_ci 83d722e3fbSopenharmony_cidrm_public struct fd_ringbuffer * 84d722e3fbSopenharmony_cifd_ringbuffer_ref(struct fd_ringbuffer *ring) 85d722e3fbSopenharmony_ci{ 86d722e3fbSopenharmony_ci STATIC_ASSERT(sizeof(ring->refcnt) <= sizeof(ring->__pad)); 87d722e3fbSopenharmony_ci atomic_inc(&ring->refcnt); 88d722e3fbSopenharmony_ci return ring; 89d722e3fbSopenharmony_ci} 90d722e3fbSopenharmony_ci 91d722e3fbSopenharmony_ci/* ringbuffers which are IB targets should set the toplevel rb (ie. 92d722e3fbSopenharmony_ci * the IB source) as it's parent before emitting reloc's, to ensure 93d722e3fbSopenharmony_ci * the bookkeeping works out properly. 94d722e3fbSopenharmony_ci */ 95d722e3fbSopenharmony_cidrm_public void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, 96d722e3fbSopenharmony_ci struct fd_ringbuffer *parent) 97d722e3fbSopenharmony_ci{ 98d722e3fbSopenharmony_ci /* state objects should not be parented! */ 99d722e3fbSopenharmony_ci assert(!(ring->flags & FD_RINGBUFFER_OBJECT)); 100d722e3fbSopenharmony_ci ring->parent = parent; 101d722e3fbSopenharmony_ci} 102d722e3fbSopenharmony_ci 103d722e3fbSopenharmony_cidrm_public void fd_ringbuffer_reset(struct fd_ringbuffer *ring) 104d722e3fbSopenharmony_ci{ 105d722e3fbSopenharmony_ci uint32_t *start = ring->start; 106d722e3fbSopenharmony_ci if (ring->pipe->id == FD_PIPE_2D) 107d722e3fbSopenharmony_ci start = &ring->start[0x140]; 108d722e3fbSopenharmony_ci ring->cur = ring->last_start = start; 109d722e3fbSopenharmony_ci if (ring->funcs->reset) 110d722e3fbSopenharmony_ci ring->funcs->reset(ring); 111d722e3fbSopenharmony_ci} 112d722e3fbSopenharmony_ci 113d722e3fbSopenharmony_cidrm_public int fd_ringbuffer_flush(struct fd_ringbuffer *ring) 114d722e3fbSopenharmony_ci{ 115d722e3fbSopenharmony_ci return ring->funcs->flush(ring, ring->last_start, -1, NULL); 116d722e3fbSopenharmony_ci} 117d722e3fbSopenharmony_ci 118d722e3fbSopenharmony_cidrm_public int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd, 119d722e3fbSopenharmony_ci int *out_fence_fd) 120d722e3fbSopenharmony_ci{ 121d722e3fbSopenharmony_ci return ring->funcs->flush(ring, ring->last_start, in_fence_fd, out_fence_fd); 122d722e3fbSopenharmony_ci} 123d722e3fbSopenharmony_ci 124d722e3fbSopenharmony_cidrm_public void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords) 125d722e3fbSopenharmony_ci{ 126d722e3fbSopenharmony_ci assert(ring->funcs->grow); /* unsupported on kgsl */ 127d722e3fbSopenharmony_ci 128d722e3fbSopenharmony_ci /* there is an upper bound on IB size, which appears to be 0x100000 */ 129d722e3fbSopenharmony_ci if (ring->size < 0x100000) 130d722e3fbSopenharmony_ci ring->size *= 2; 131d722e3fbSopenharmony_ci 132d722e3fbSopenharmony_ci ring->funcs->grow(ring, ring->size); 133d722e3fbSopenharmony_ci 134d722e3fbSopenharmony_ci ring->start = ring->funcs->hostptr(ring); 135d722e3fbSopenharmony_ci ring->end = &(ring->start[ring->size/4]); 136d722e3fbSopenharmony_ci 137d722e3fbSopenharmony_ci ring->cur = ring->last_start = ring->start; 138d722e3fbSopenharmony_ci} 139d722e3fbSopenharmony_ci 140d722e3fbSopenharmony_cidrm_public uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring) 141d722e3fbSopenharmony_ci{ 142d722e3fbSopenharmony_ci return ring->last_timestamp; 143d722e3fbSopenharmony_ci} 144d722e3fbSopenharmony_ci 145d722e3fbSopenharmony_cidrm_public void fd_ringbuffer_reloc(struct fd_ringbuffer *ring, 146d722e3fbSopenharmony_ci const struct fd_reloc *reloc) 147d722e3fbSopenharmony_ci{ 148d722e3fbSopenharmony_ci assert(ring->pipe->gpu_id < 500); 149d722e3fbSopenharmony_ci ring->funcs->emit_reloc(ring, reloc); 150d722e3fbSopenharmony_ci} 151d722e3fbSopenharmony_ci 152d722e3fbSopenharmony_cidrm_public void fd_ringbuffer_reloc2(struct fd_ringbuffer *ring, 153d722e3fbSopenharmony_ci const struct fd_reloc *reloc) 154d722e3fbSopenharmony_ci{ 155d722e3fbSopenharmony_ci ring->funcs->emit_reloc(ring, reloc); 156d722e3fbSopenharmony_ci} 157d722e3fbSopenharmony_ci 158d722e3fbSopenharmony_cidrm_public uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring) 159d722e3fbSopenharmony_ci{ 160d722e3fbSopenharmony_ci if (!ring->funcs->cmd_count) 161d722e3fbSopenharmony_ci return 1; 162d722e3fbSopenharmony_ci return ring->funcs->cmd_count(ring); 163d722e3fbSopenharmony_ci} 164d722e3fbSopenharmony_ci 165d722e3fbSopenharmony_cidrm_public uint32_t 166d722e3fbSopenharmony_cifd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, 167d722e3fbSopenharmony_ci struct fd_ringbuffer *target, uint32_t cmd_idx) 168d722e3fbSopenharmony_ci{ 169d722e3fbSopenharmony_ci return ring->funcs->emit_reloc_ring(ring, target, cmd_idx); 170d722e3fbSopenharmony_ci} 171d722e3fbSopenharmony_ci 172d722e3fbSopenharmony_cidrm_public uint32_t 173d722e3fbSopenharmony_cifd_ringbuffer_size(struct fd_ringbuffer *ring) 174d722e3fbSopenharmony_ci{ 175d722e3fbSopenharmony_ci /* only really needed for stateobj ringbuffers, and won't really 176d722e3fbSopenharmony_ci * do what you expect for growable rb's.. so lets just restrict 177d722e3fbSopenharmony_ci * this to stateobj's for now: 178d722e3fbSopenharmony_ci */ 179d722e3fbSopenharmony_ci assert(ring->flags & FD_RINGBUFFER_OBJECT); 180d722e3fbSopenharmony_ci return offset_bytes(ring->cur, ring->start); 181d722e3fbSopenharmony_ci} 182d722e3fbSopenharmony_ci 183