1e88f27b3Smrg/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2e88f27b3Smrg
3e88f27b3Smrg/*
4e88f27b3Smrg * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5e88f27b3Smrg *
6e88f27b3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7e88f27b3Smrg * copy of this software and associated documentation files (the "Software"),
8e88f27b3Smrg * to deal in the Software without restriction, including without limitation
9e88f27b3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10e88f27b3Smrg * and/or sell copies of the Software, and to permit persons to whom the
11e88f27b3Smrg * Software is furnished to do so, subject to the following conditions:
12e88f27b3Smrg *
13e88f27b3Smrg * The above copyright notice and this permission notice (including the next
14e88f27b3Smrg * paragraph) shall be included in all copies or substantial portions of the
15e88f27b3Smrg * Software.
16e88f27b3Smrg *
17e88f27b3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18e88f27b3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19e88f27b3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20e88f27b3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21e88f27b3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22e88f27b3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23e88f27b3Smrg * SOFTWARE.
24e88f27b3Smrg *
25e88f27b3Smrg * Authors:
26e88f27b3Smrg *    Rob Clark <robclark@freedesktop.org>
27e88f27b3Smrg */
28e88f27b3Smrg
29e88f27b3Smrg#include <assert.h>
30e88f27b3Smrg
31e88f27b3Smrg#include "freedreno_drmif.h"
32e88f27b3Smrg#include "freedreno_priv.h"
33e88f27b3Smrg#include "freedreno_ringbuffer.h"
34e88f27b3Smrg
357cdc0497Smrgdrm_public struct fd_ringbuffer *
367cdc0497Smrgfd_ringbuffer_new_flags(struct fd_pipe *pipe, uint32_t size,
377cdc0497Smrg		enum fd_ringbuffer_flags flags)
38e88f27b3Smrg{
39e88f27b3Smrg	struct fd_ringbuffer *ring;
40e88f27b3Smrg
417cdc0497Smrg	/* we can't really support "growable" rb's in general for
427cdc0497Smrg	 * stateobj's since we need a single gpu addr (ie. can't
437cdc0497Smrg	 * do the trick of a chain of IB packets):
447cdc0497Smrg	 */
457cdc0497Smrg	if (flags & FD_RINGBUFFER_OBJECT)
467cdc0497Smrg		assert(size);
477cdc0497Smrg
487cdc0497Smrg	ring = pipe->funcs->ringbuffer_new(pipe, size, flags);
49e88f27b3Smrg	if (!ring)
50e88f27b3Smrg		return NULL;
51e88f27b3Smrg
527cdc0497Smrg	ring->flags = flags;
53e88f27b3Smrg	ring->pipe = pipe;
54e88f27b3Smrg	ring->start = ring->funcs->hostptr(ring);
553f012e29Smrg	ring->end = &(ring->start[ring->size/4]);
56e88f27b3Smrg
57e88f27b3Smrg	ring->cur = ring->last_start = ring->start;
58e88f27b3Smrg
59e88f27b3Smrg	return ring;
60e88f27b3Smrg}
61e88f27b3Smrg
627cdc0497Smrgdrm_public struct fd_ringbuffer *
637cdc0497Smrgfd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size)
647cdc0497Smrg{
657cdc0497Smrg	return fd_ringbuffer_new_flags(pipe, size, 0);
667cdc0497Smrg}
677cdc0497Smrg
687cdc0497Smrgdrm_public struct fd_ringbuffer *
697cdc0497Smrgfd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size)
707cdc0497Smrg{
717cdc0497Smrg	return fd_ringbuffer_new_flags(pipe, size, FD_RINGBUFFER_OBJECT);
727cdc0497Smrg}
737cdc0497Smrg
747cdc0497Smrgdrm_public void fd_ringbuffer_del(struct fd_ringbuffer *ring)
75e88f27b3Smrg{
767cdc0497Smrg	if (!atomic_dec_and_test(&ring->refcnt))
777cdc0497Smrg		return;
787cdc0497Smrg
793f012e29Smrg	fd_ringbuffer_reset(ring);
80e88f27b3Smrg	ring->funcs->destroy(ring);
81e88f27b3Smrg}
82e88f27b3Smrg
837cdc0497Smrgdrm_public struct fd_ringbuffer *
847cdc0497Smrgfd_ringbuffer_ref(struct fd_ringbuffer *ring)
857cdc0497Smrg{
867cdc0497Smrg	STATIC_ASSERT(sizeof(ring->refcnt) <= sizeof(ring->__pad));
877cdc0497Smrg	atomic_inc(&ring->refcnt);
887cdc0497Smrg	return ring;
897cdc0497Smrg}
907cdc0497Smrg
91e88f27b3Smrg/* ringbuffers which are IB targets should set the toplevel rb (ie.
92e88f27b3Smrg * the IB source) as it's parent before emitting reloc's, to ensure
93e88f27b3Smrg * the bookkeeping works out properly.
94e88f27b3Smrg */
957cdc0497Smrgdrm_public void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring,
96baaff307Smrg					 struct fd_ringbuffer *parent)
97e88f27b3Smrg{
987cdc0497Smrg	/* state objects should not be parented! */
997cdc0497Smrg	assert(!(ring->flags & FD_RINGBUFFER_OBJECT));
100e88f27b3Smrg	ring->parent = parent;
101e88f27b3Smrg}
102e88f27b3Smrg
1037cdc0497Smrgdrm_public void fd_ringbuffer_reset(struct fd_ringbuffer *ring)
104e88f27b3Smrg{
105e88f27b3Smrg	uint32_t *start = ring->start;
106e88f27b3Smrg	if (ring->pipe->id == FD_PIPE_2D)
107e88f27b3Smrg		start = &ring->start[0x140];
108e88f27b3Smrg	ring->cur = ring->last_start = start;
109857b0bc6Smrg	if (ring->funcs->reset)
110857b0bc6Smrg		ring->funcs->reset(ring);
111e88f27b3Smrg}
112e88f27b3Smrg
1137cdc0497Smrgdrm_public int fd_ringbuffer_flush(struct fd_ringbuffer *ring)
114e88f27b3Smrg{
115037b3c26Smrg	return ring->funcs->flush(ring, ring->last_start, -1, NULL);
116037b3c26Smrg}
117037b3c26Smrg
1187cdc0497Smrgdrm_public int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd,
119037b3c26Smrg		int *out_fence_fd)
120037b3c26Smrg{
121037b3c26Smrg	return ring->funcs->flush(ring, ring->last_start, in_fence_fd, out_fence_fd);
122e88f27b3Smrg}
123e88f27b3Smrg
1247cdc0497Smrgdrm_public void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords)
1253f012e29Smrg{
1263f012e29Smrg	assert(ring->funcs->grow);     /* unsupported on kgsl */
1273f012e29Smrg
1283f012e29Smrg	/* there is an upper bound on IB size, which appears to be 0x100000 */
1293f012e29Smrg	if (ring->size < 0x100000)
1303f012e29Smrg		ring->size *= 2;
1313f012e29Smrg
1323f012e29Smrg	ring->funcs->grow(ring, ring->size);
1333f012e29Smrg
1343f012e29Smrg	ring->start = ring->funcs->hostptr(ring);
1353f012e29Smrg	ring->end = &(ring->start[ring->size/4]);
1363f012e29Smrg
1373f012e29Smrg	ring->cur = ring->last_start = ring->start;
1383f012e29Smrg}
1393f012e29Smrg
1407cdc0497Smrgdrm_public uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring)
141e88f27b3Smrg{
142e88f27b3Smrg	return ring->last_timestamp;
143e88f27b3Smrg}
144e88f27b3Smrg
1457cdc0497Smrgdrm_public void fd_ringbuffer_reloc(struct fd_ringbuffer *ring,
146baaff307Smrg				    const struct fd_reloc *reloc)
147037b3c26Smrg{
148037b3c26Smrg	assert(ring->pipe->gpu_id < 500);
149037b3c26Smrg	ring->funcs->emit_reloc(ring, reloc);
150037b3c26Smrg}
151037b3c26Smrg
1527cdc0497Smrgdrm_public void fd_ringbuffer_reloc2(struct fd_ringbuffer *ring,
153037b3c26Smrg				     const struct fd_reloc *reloc)
154e88f27b3Smrg{
155e88f27b3Smrg	ring->funcs->emit_reloc(ring, reloc);
156e88f27b3Smrg}
157e88f27b3Smrg
1587cdc0497Smrgdrm_public uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
1593f012e29Smrg{
1603f012e29Smrg	if (!ring->funcs->cmd_count)
1613f012e29Smrg		return 1;
1623f012e29Smrg	return ring->funcs->cmd_count(ring);
1633f012e29Smrg}
1643f012e29Smrg
1657cdc0497Smrgdrm_public uint32_t
1663f012e29Smrgfd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring,
1673f012e29Smrg		struct fd_ringbuffer *target, uint32_t cmd_idx)
1683f012e29Smrg{
1697cdc0497Smrg	return ring->funcs->emit_reloc_ring(ring, target, cmd_idx);
170e88f27b3Smrg}
171e88f27b3Smrg
1727cdc0497Smrgdrm_public uint32_t
1737cdc0497Smrgfd_ringbuffer_size(struct fd_ringbuffer *ring)
174e88f27b3Smrg{
1757cdc0497Smrg	/* only really needed for stateobj ringbuffers, and won't really
1767cdc0497Smrg	 * do what you expect for growable rb's.. so lets just restrict
1777cdc0497Smrg	 * this to stateobj's for now:
1787cdc0497Smrg	 */
1797cdc0497Smrg	assert(ring->flags & FD_RINGBUFFER_OBJECT);
1807cdc0497Smrg	return offset_bytes(ring->cur, ring->start);
181e88f27b3Smrg}
182e88f27b3Smrg
183