summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <robclark@freedesktop.org>2012-10-07 18:57:31 -0500
committerRob Clark <robclark@freedesktop.org>2013-02-14 12:13:15 -0500
commit41fc2cc8a98a8d02ea7d3635d3103f7dd371de10 (patch)
tree10d8aab5a340486a34f00052cb110d3ff3d93208
parent36d18211b196cad4761ac70c4fd08aba323f5b0d (diff)
freedreno: add freedreno DRM
The libdrm_freedreno helper layer for use by xf86-video-freedreno, fdre (freedreno r/e library and tests for driving gpu), and eventual gallium driver for the Adreno GPU. This uses the msm gpu driver from QCOM's android kernel tree. Note that current msm kernel driver is a bit strange. It provides a DRM interface for GEM, which is basically sufficient to have DRI2 working. But it does not provide KMS. And interface to 2d and 3d cores is via different other devices (/dev/kgsl-*). This is not quite how I'd write a DRM driver, but at this stage it is useful for xf86-video-freedreno and fdre (and eventual gallium driver) to be able to work on existing kernel driver from QCOM, to allow to capture cmdstream dumps from the binary blob drivers without having to reboot. So libdrm_freedreno attempts to hide most of the crazy. The intention is that when there is a proper kernel driver, it will be mostly just changes in libdrm_freedreno to adapt the gallium driver and xf86-video-freedreno (ignoring the fbdev->KMS changes). So don't look at freedreno as an example of how to write a libdrm module or a DRM driver.. it is just an attempt to paper over a non- standard kernel driver architecture. v1: original v2: hold ref's to pending bo's (because qcom's kernel driver doesn't), various bug fixes, add ringbuffer markers so we can emit IB's to portion of ringbuffer (so that gallium driver can use a single ringbuffer for both tile cmds and draw cmds. Signed-off-by: Rob Clark <robclark@freedesktop.org>
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac15
-rw-r--r--freedreno/Makefile.am19
-rw-r--r--freedreno/README16
-rw-r--r--freedreno/freedreno_bo.c274
-rw-r--r--freedreno/freedreno_device.c45
-rw-r--r--freedreno/freedreno_drmif.h99
-rw-r--r--freedreno/freedreno_pipe.c227
-rw-r--r--freedreno/freedreno_priv.h117
-rw-r--r--freedreno/freedreno_ringbuffer.c249
-rw-r--r--freedreno/freedreno_ringbuffer.h87
-rw-r--r--freedreno/kgsl_drm.h192
-rw-r--r--freedreno/libdrm_freedreno.pc.in11
-rw-r--r--freedreno/list.h137
-rw-r--r--freedreno/msm_kgsl.h519
16 files changed, 2012 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 225fd801..9f8eabbf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,6 +48,7 @@ libdrm_nouveau.pc
48libdrm_radeon.pc 48libdrm_radeon.pc
49libdrm_omap.pc 49libdrm_omap.pc
50libdrm_exynos.pc 50libdrm_exynos.pc
51libdrm_freedreno.pc
51libkms.pc 52libkms.pc
52libtool 53libtool
53ltmain.sh 54ltmain.sh
diff --git a/Makefile.am b/Makefile.am
index 94572d01..f7260368 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,7 +47,11 @@ if HAVE_EXYNOS
47EXYNOS_SUBDIR = exynos 47EXYNOS_SUBDIR = exynos
48endif 48endif
49 49
50SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man 50if HAVE_FREEDRENO
51FREEDRENO_SUBDIR = freedreno
52endif
53
54SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) tests include man
51 55
52libdrm_la_LTLIBRARIES = libdrm.la 56libdrm_la_LTLIBRARIES = libdrm.la
53libdrm_ladir = $(libdir) 57libdrm_ladir = $(libdir)
diff --git a/configure.ac b/configure.ac
index e2e34667..83ffe1b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,6 +93,11 @@ AC_ARG_ENABLE(exynos-experimental-api,
93 [Enable support for EXYNOS's experimental API (default: disabled)]), 93 [Enable support for EXYNOS's experimental API (default: disabled)]),
94 [EXYNOS=$enableval], [EXYNOS=no]) 94 [EXYNOS=$enableval], [EXYNOS=no])
95 95
96AC_ARG_ENABLE(freedreno-experimental-api,
97 AS_HELP_STRING([--enable-freedreno-experimental-api],
98 [Enable support for freedreno's experimental API (default: disabled)]),
99 [FREEDRENO=$enableval], [FREEDRENO=no])
100
96dnl =========================================================================== 101dnl ===========================================================================
97dnl check compiler flags 102dnl check compiler flags
98AC_DEFUN([LIBDRM_CC_TRY_FLAG], [ 103AC_DEFUN([LIBDRM_CC_TRY_FLAG], [
@@ -201,6 +206,11 @@ if test "x$EXYNOS" = xyes; then
201 AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support]) 206 AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support])
202fi 207fi
203 208
209AM_CONDITIONAL(HAVE_FREEDRENO, [test "x$FREEDRENO" = xyes])
210if test "x$FREEDRENO" = xyes; then
211 AC_DEFINE(HAVE_FREEDRENO, 1, [Have freedreno support])
212fi
213
204AC_ARG_ENABLE([cairo-tests], 214AC_ARG_ENABLE([cairo-tests],
205 [AS_HELP_STRING([--enable-cairo-tests], 215 [AS_HELP_STRING([--enable-cairo-tests],
206 [Enable support for Cairo rendering in tests (default: auto)])], 216 [Enable support for Cairo rendering in tests (default: auto)])],
@@ -247,7 +257,7 @@ else
247fi 257fi
248AM_CONDITIONAL([HAVE_MANPAGES_STYLESHEET], [test "x$HAVE_MANPAGES_STYLESHEET" = "xyes"]) 258AM_CONDITIONAL([HAVE_MANPAGES_STYLESHEET], [test "x$HAVE_MANPAGES_STYLESHEET" = "xyes"])
249 259
250if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno"; then 260if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno" -o "x$FREEDRENO" != "xno"; then
251 # Check for atomic intrinsics 261 # Check for atomic intrinsics
252 AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives, 262 AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
253 [ 263 [
@@ -358,6 +368,8 @@ AC_CONFIG_FILES([
358 omap/libdrm_omap.pc 368 omap/libdrm_omap.pc
359 exynos/Makefile 369 exynos/Makefile
360 exynos/libdrm_exynos.pc 370 exynos/libdrm_exynos.pc
371 freedreno/Makefile
372 freedreno/libdrm_freedreno.pc
361 tests/Makefile 373 tests/Makefile
362 tests/modeprint/Makefile 374 tests/modeprint/Makefile
363 tests/modetest/Makefile 375 tests/modetest/Makefile
@@ -380,4 +392,5 @@ echo " Radeon API $RADEON"
380echo " Nouveau API $NOUVEAU" 392echo " Nouveau API $NOUVEAU"
381echo " OMAP API $OMAP" 393echo " OMAP API $OMAP"
382echo " EXYNOS API $EXYNOS" 394echo " EXYNOS API $EXYNOS"
395echo " Freedreno API $FREEDRENO"
383echo "" 396echo ""
diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am
new file mode 100644
index 00000000..f46a7807
--- /dev/null
+++ b/freedreno/Makefile.am
@@ -0,0 +1,19 @@
1AM_CFLAGS = \
2 $(WARN_CFLAGS) \
3 -I$(top_srcdir) \
4 -I$(top_srcdir)/freedreno \
5 $(PTHREADSTUBS_CFLAGS) \
6 -I$(top_srcdir)/include/drm
7
8libdrm_freedreno_la_LTLIBRARIES = libdrm_freedreno.la
9libdrm_freedreno_ladir = $(libdir)
10libdrm_freedreno_la_LDFLAGS = -version-number 1:0:0 -no-undefined
11libdrm_freedreno_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
12
13libdrm_freedreno_la_SOURCES = freedreno_device.c freedreno_pipe.c freedreno_ringbuffer.c freedreno_bo.c
14
15libdrm_freedrenocommonincludedir = ${includedir}/freedreno
16libdrm_freedrenocommoninclude_HEADERS = freedreno_drmif.h freedreno_ringbuffer.h
17
18pkgconfigdir = @pkgconfigdir@
19pkgconfig_DATA = libdrm_freedreno.pc
diff --git a/freedreno/README b/freedreno/README
new file mode 100644
index 00000000..ae22e013
--- /dev/null
+++ b/freedreno/README
@@ -0,0 +1,16 @@
1Note that current msm kernel driver is a bit strange. It provides a
2DRM interface for GEM, which is basically sufficient to have DRI2
3working. But it does not provide KMS. And interface to 2d and 3d
4cores is via different other devices (/dev/kgsl-*). This is not
5quite how I'd write a DRM driver, but at this stage it is useful for
6xf86-video-freedreno and fdre (and eventual gallium driver) to be
7able to work on existing kernel driver from QCOM, to allow to
8capture cmdstream dumps from the binary blob drivers without having
9to reboot. So libdrm_freedreno attempts to hide most of the crazy.
10The intention is that when there is a proper kernel driver, it will
11be mostly just changes in libdrm_freedreno to adapt the gallium
12driver and xf86-video-freedreno (ignoring the fbdev->KMS changes).
13
14So don't look at freedreno as an example of how to write a libdrm
15module or a DRM driver.. it is just an attempt to paper over a non-
16standard kernel driver architecture.
diff --git a/freedreno/freedreno_bo.c b/freedreno/freedreno_bo.c
new file mode 100644
index 00000000..4f566e10
--- /dev/null
+++ b/freedreno/freedreno_bo.c
@@ -0,0 +1,274 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#include "freedreno_drmif.h"
30#include "freedreno_priv.h"
31
32#include <linux/fb.h>
33
34static struct fd_bo * bo_from_handle(struct fd_device *dev,
35 uint32_t size, uint32_t handle)
36{
37 unsigned i;
38 struct fd_bo *bo = calloc(1, sizeof(*bo));
39 if (!bo)
40 return NULL;
41 bo->dev = dev;
42 bo->size = size;
43 bo->handle = handle;
44 atomic_set(&bo->refcnt, 1);
45 for (i = 0; i < ARRAY_SIZE(bo->list); i++)
46 list_inithead(&bo->list[i]);
47 return bo;
48}
49
50static int set_memtype(struct fd_bo *bo, uint32_t flags)
51{
52 struct drm_kgsl_gem_memtype req = {
53 .handle = bo->handle,
54 .type = flags & DRM_FREEDRENO_GEM_TYPE_MEM_MASK,
55 };
56
57 return drmCommandWrite(bo->dev->fd, DRM_KGSL_GEM_SETMEMTYPE,
58 &req, sizeof(req));
59}
60
61static int bo_alloc(struct fd_bo *bo)
62{
63 if (!bo->offset) {
64 struct drm_kgsl_gem_alloc req = {
65 .handle = bo->handle,
66 };
67 int ret;
68
69 /* if the buffer is already backed by pages then this
70 * doesn't actually do anything (other than giving us
71 * the offset)
72 */
73 ret = drmCommandWriteRead(bo->dev->fd, DRM_KGSL_GEM_ALLOC,
74 &req, sizeof(req));
75 if (ret) {
76 ERROR_MSG("alloc failed: %s", strerror(errno));
77 return ret;
78 }
79
80 bo->offset = req.offset;
81 }
82 return 0;
83}
84
85struct fd_bo * fd_bo_new(struct fd_device *dev,
86 uint32_t size, uint32_t flags)
87{
88 struct drm_kgsl_gem_create req = {
89 .size = ALIGN(size, 4096),
90 };
91 struct fd_bo *bo = NULL;
92
93 if (drmCommandWriteRead(dev->fd, DRM_KGSL_GEM_CREATE,
94 &req, sizeof(req))) {
95 return NULL;
96 }
97
98 bo = bo_from_handle(dev, size, req.handle);
99 if (!bo) {
100 goto fail;
101 }
102
103 if (set_memtype(bo, flags)) {
104 goto fail;
105 }
106
107 return bo;
108fail:
109 if (bo)
110 fd_bo_del(bo);
111 return NULL;
112}
113
114/* don't use this... it is just needed to get a bo from the
115 * framebuffer (pre-dmabuf)
116 */
117struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe,
118 int fbfd, uint32_t size)
119{
120 struct drm_kgsl_gem_create_fd req = {
121 .fd = fbfd,
122 };
123 struct fd_bo *bo;
124
125 if (drmCommandWriteRead(pipe->dev->fd, DRM_KGSL_GEM_CREATE_FD,
126 &req, sizeof(req))) {
127 return NULL;
128 }
129
130 bo = bo_from_handle(pipe->dev, size, req.handle);
131
132 /* this is fugly, but works around a bug in the kernel..
133 * priv->memdesc.size never gets set, so getbufinfo ioctl
134 * thinks the buffer hasn't be allocate and fails
135 */
136 if (bo && !fd_bo_gpuaddr(bo, 0)) {
137 void *fbmem = mmap(NULL, size, PROT_READ | PROT_WRITE,
138 MAP_SHARED, fbfd, 0);
139 struct kgsl_map_user_mem req = {
140 .memtype = KGSL_USER_MEM_TYPE_ADDR,
141 .len = size,
142 .offset = 0,
143 .hostptr = (unsigned long)fbmem,
144 };
145 int ret;
146 ret = ioctl(pipe->fd, IOCTL_KGSL_MAP_USER_MEM, &req);
147 if (ret) {
148 ERROR_MSG("mapping user mem failed: %s",
149 strerror(errno));
150 goto fail;
151 }
152 bo->gpuaddr = req.gpuaddr;
153 bo->map = fbmem;
154 }
155
156 return bo;
157fail:
158 if (bo)
159 fd_bo_del(bo);
160 return NULL;
161}
162
163struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name)
164{
165 struct drm_gem_open req = {
166 .name = name,
167 };
168
169 if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
170 return NULL;
171 }
172
173 return bo_from_handle(dev, req.size, req.handle);
174}
175
176struct fd_bo * fd_bo_ref(struct fd_bo *bo)
177{
178 atomic_inc(&bo->refcnt);
179 return bo;
180}
181
182void fd_bo_del(struct fd_bo *bo)
183{
184 if (!atomic_dec_and_test(&bo->refcnt))
185 return;
186
187 if (bo->map)
188 munmap(bo->map, bo->size);
189
190 if (bo->handle) {
191 struct drm_gem_close req = {
192 .handle = bo->handle,
193 };
194 drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
195 }
196
197 free(bo);
198}
199
200int fd_bo_get_name(struct fd_bo *bo, uint32_t *name)
201{
202 if (!bo->name) {
203 struct drm_gem_flink req = {
204 .handle = bo->handle,
205 };
206 int ret;
207
208 ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
209 if (ret) {
210 return ret;
211 }
212
213 bo->name = req.name;
214 }
215
216 *name = bo->name;
217
218 return 0;
219}
220
221uint32_t fd_bo_handle(struct fd_bo *bo)
222{
223 return bo->handle;
224}
225
226uint32_t fd_bo_size(struct fd_bo *bo)
227{
228 return bo->size;
229}
230
231void * fd_bo_map(struct fd_bo *bo)
232{
233 if (!bo->map) {
234 int ret;
235
236 ret = bo_alloc(bo);
237 if (ret) {
238 return NULL;
239 }
240
241 bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
242 bo->dev->fd, bo->offset);
243 if (bo->map == MAP_FAILED) {
244 ERROR_MSG("mmap failed: %s", strerror(errno));
245 bo->map = NULL;
246 }
247 }
248 return bo->map;
249}
250
251uint32_t fd_bo_gpuaddr(struct fd_bo *bo, uint32_t offset)
252{
253 if (!bo->gpuaddr) {
254 struct drm_kgsl_gem_bufinfo req = {
255 .handle = bo->handle,
256 };
257 int ret;
258
259 ret = bo_alloc(bo);
260 if (ret) {
261 return ret;
262 }
263
264 ret = drmCommandWriteRead(bo->dev->fd, DRM_KGSL_GEM_GET_BUFINFO,
265 &req, sizeof(req));
266 if (ret) {
267 ERROR_MSG("get bufinfo failed: %s", strerror(errno));
268 return 0;
269 }
270
271 bo->gpuaddr = req.gpuaddr[0];
272 }
273 return bo->gpuaddr + offset;
274}
diff --git a/freedreno/freedreno_device.c b/freedreno/freedreno_device.c
new file mode 100644
index 00000000..0a9ef9f2
--- /dev/null
+++ b/freedreno/freedreno_device.c
@@ -0,0 +1,45 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#include "freedreno_drmif.h"
30#include "freedreno_priv.h"
31
32struct fd_device * fd_device_new(int fd)
33{
34 struct fd_device *dev = calloc(1, sizeof(*dev));
35 if (!dev)
36 return NULL;
37 dev->fd = fd;
38 return dev;
39}
40
41void fd_device_del(struct fd_device *dev)
42{
43 free(dev);
44}
45
diff --git a/freedreno/freedreno_drmif.h b/freedreno/freedreno_drmif.h
new file mode 100644
index 00000000..775d6995
--- /dev/null
+++ b/freedreno/freedreno_drmif.h
@@ -0,0 +1,99 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#ifndef FREEDRENO_DRMIF_H_
30#define FREEDRENO_DRMIF_H_
31
32#include <xf86drm.h>
33#include <stdint.h>
34
35struct fd_bo;
36struct fd_pipe;
37struct fd_device;
38
39enum fd_pipe_id {
40 FD_PIPE_3D = 1,
41 FD_PIPE_2D = 2,
42 /* some devices have two 2d blocks.. not really sure how to
43 * use that yet, so just ignoring the 2nd 2d pipe for now
44 */
45 FD_PIPE_MAX
46};
47
48enum fd_param_id {
49 FD_DEVICE_ID,
50 FD_GMEM_SIZE,
51};
52
53/* bo flags: */
54#define DRM_FREEDRENO_GEM_TYPE_SMI 0x00000001
55#define DRM_FREEDRENO_GEM_TYPE_KMEM 0x00000002
56#define DRM_FREEDRENO_GEM_TYPE_MEM_MASK 0x0000000f
57#define DRM_FREEDRENO_GEM_CACHE_NONE 0x00000000
58#define DRM_FREEDRENO_GEM_CACHE_WCOMBINE 0x00100000
59#define DRM_FREEDRENO_GEM_CACHE_WTHROUGH 0x00200000
60#define DRM_FREEDRENO_GEM_CACHE_WBACK 0x00400000
61#define DRM_FREEDRENO_GEM_CACHE_WBACKWA 0x00800000
62#define DRM_FREEDRENO_GEM_CACHE_MASK 0x00f00000
63#define DRM_FREEDRENO_GEM_GPUREADONLY 0x01000000
64
65
66/* device functions:
67 */
68
69struct fd_device * fd_device_new(int fd);
70void fd_device_del(struct fd_device *dev);
71
72
73/* pipe functions:
74 */
75
76struct fd_pipe * fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id);
77void fd_pipe_del(struct fd_pipe *pipe);
78int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param,
79 uint64_t *value);
80int fd_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp);
81int fd_pipe_timestamp(struct fd_pipe *pipe, uint32_t *timestamp);
82
83
84/* buffer-object functions:
85 */
86
87struct fd_bo * fd_bo_new(struct fd_device *dev,
88 uint32_t size, uint32_t flags);
89struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe,
90 int fbfd, uint32_t size);
91struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name);
92struct fd_bo * fd_bo_ref(struct fd_bo *bo);
93void fd_bo_del(struct fd_bo *bo);
94int fd_bo_get_name(struct fd_bo *bo, uint32_t *name);
95uint32_t fd_bo_handle(struct fd_bo *bo);
96uint32_t fd_bo_size(struct fd_bo *bo);
97void * fd_bo_map(struct fd_bo *bo);
98
99#endif /* FREEDRENO_DRMIF_H_ */
diff --git a/freedreno/freedreno_pipe.c b/freedreno/freedreno_pipe.c
new file mode 100644
index 00000000..49949ecc
--- /dev/null
+++ b/freedreno/freedreno_pipe.c
@@ -0,0 +1,227 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#include "freedreno_drmif.h"
30#include "freedreno_priv.h"
31
32
33static int getprop(int fd, enum kgsl_property_type type,
34 void *value, int sizebytes)
35{
36 struct kgsl_device_getproperty req = {
37 .type = type,
38 .value = value,
39 .sizebytes = sizebytes,
40 };
41 return ioctl(fd, IOCTL_KGSL_DEVICE_GETPROPERTY, &req);
42}
43
44#define GETPROP(fd, prop, x) do { \
45 if (getprop((fd), KGSL_PROP_##prop, &(x), sizeof(x))) { \
46 ERROR_MSG("failed to get property: " #prop); \
47 goto fail; \
48 } } while (0)
49
50
51struct fd_pipe * fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
52{
53 static const char *paths[] = {
54 [FD_PIPE_3D] = "/dev/kgsl-3d0",
55 [FD_PIPE_2D] = "/dev/kgsl-2d0",
56 };
57 struct kgsl_drawctxt_create req = {
58 .flags = 0x2000, /* ??? */
59 };
60 struct fd_pipe *pipe = NULL;
61 int ret, fd;
62
63 if (id > FD_PIPE_MAX) {
64 ERROR_MSG("invalid pipe id: %d", id);
65 goto fail;
66 }
67
68 fd = open(paths[id], O_RDWR);
69 if (fd < 0) {
70 ERROR_MSG("could not open %s device: %d (%s)",
71 paths[id], fd, strerror(errno));
72 goto fail;
73 }
74
75 ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &req);
76 if (ret) {
77 ERROR_MSG("failed to allocate context: %d (%s)",
78 ret, strerror(errno));
79 goto fail;
80 }
81
82 pipe = calloc(1, sizeof(*pipe));
83 if (!pipe) {
84 ERROR_MSG("allocation failed");
85 goto fail;
86 }
87
88 pipe->dev = dev;
89 pipe->id = id;
90 pipe->fd = fd;
91 pipe->drawctxt_id = req.drawctxt_id;
92
93 list_inithead(&pipe->submit_list);
94 list_inithead(&pipe->pending_list);
95
96 GETPROP(fd, VERSION, pipe->version);
97 GETPROP(fd, DEVICE_INFO, pipe->devinfo);
98
99 INFO_MSG("Pipe Info:");
100 INFO_MSG(" Device: %s", paths[id]);
101 INFO_MSG(" Chip-id: %d.%d.%d.%d",
102 (pipe->devinfo.chip_id >> 24) & 0xff,
103 (pipe->devinfo.chip_id >> 16) & 0xff,
104 (pipe->devinfo.chip_id >> 8) & 0xff,
105 (pipe->devinfo.chip_id >> 0) & 0xff);
106 INFO_MSG(" Device-id: %d", pipe->devinfo.device_id);
107 INFO_MSG(" GPU-id: %d", pipe->devinfo.gpu_id);
108 INFO_MSG(" MMU enabled: %d", pipe->devinfo.mmu_enabled);
109 INFO_MSG(" GMEM Base addr: 0x%08x", pipe->devinfo.gmem_gpubaseaddr);
110 INFO_MSG(" GMEM size: 0x%08x", pipe->devinfo.gmem_sizebytes);
111 INFO_MSG(" Driver version: %d.%d",
112 pipe->version.drv_major, pipe->version.drv_minor);
113 INFO_MSG(" Device version: %d.%d",
114 pipe->version.dev_major, pipe->version.dev_minor);
115
116 return pipe;
117fail:
118 if (pipe)
119 fd_pipe_del(pipe);
120 return NULL;
121}
122
123void fd_pipe_del(struct fd_pipe *pipe)
124{
125 struct kgsl_drawctxt_destroy req = {
126 .drawctxt_id = pipe->drawctxt_id,
127 };
128
129 if (pipe->drawctxt_id)
130 ioctl(pipe->fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &req);
131
132 if (pipe->fd)
133 close(pipe->fd);
134
135 free(pipe);
136}
137
138int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param,
139 uint64_t *value)
140{
141 switch (param) {
142 case FD_DEVICE_ID:
143 *value = pipe->devinfo.device_id;
144 return 0;
145 case FD_GMEM_SIZE:
146 *value = pipe->devinfo.gmem_sizebytes;
147 return 0;
148 default:
149 ERROR_MSG("invalid param id: %d", param);
150 return -1;
151 }
152}
153
154int fd_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp)
155{
156 struct kgsl_device_waittimestamp req = {
157 .timestamp = timestamp,
158 .timeout = 5000,
159 };
160 int ret;
161
162 do {
163 ret = ioctl(pipe->fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP, &req);
164 } while ((ret == -1) && ((errno == EINTR) || (errno == EAGAIN)));
165 if (ret)
166 ERROR_MSG("waittimestamp failed! %d (%s)", ret, strerror(errno));
167 else
168 fd_pipe_process_pending(pipe, timestamp);
169 return ret;
170}
171
172int fd_pipe_timestamp(struct fd_pipe *pipe, uint32_t *timestamp)
173{
174 struct kgsl_cmdstream_readtimestamp req = {
175 .type = KGSL_TIMESTAMP_RETIRED
176 };
177 int ret = ioctl(pipe->fd, IOCTL_KGSL_CMDSTREAM_READTIMESTAMP, &req);
178 if (ret) {
179 ERROR_MSG("readtimestamp failed! %d (%s)",
180 ret, strerror(errno));
181 return ret;
182 }
183 *timestamp = req.timestamp;
184 return 0;
185}
186
187/* add buffer to submit list when it is referenced in cmdstream: */
188void fd_pipe_add_submit(struct fd_pipe *pipe, struct fd_bo *bo)
189{
190 struct list_head *list = &bo->list[pipe->id];
191 if (LIST_IS_EMPTY(list)) {
192 fd_bo_ref(bo);
193 } else {
194 list_del(list);
195 }
196 list_addtail(list, &pipe->submit_list);
197}
198
199/* process buffers on submit list after flush: */
200void fd_pipe_process_submit(struct fd_pipe *pipe, uint32_t timestamp)
201{
202 struct fd_bo *bo, *tmp;
203
204 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &pipe->submit_list, list[pipe->id]) {
205 struct list_head *list = &bo->list[pipe->id];
206 list_del(list);
207 bo->timestamp[pipe->id] = timestamp;
208 list_addtail(list, &pipe->pending_list);
209 }
210
211 if (!fd_pipe_timestamp(pipe, &timestamp))
212 fd_pipe_process_pending(pipe, timestamp);
213}
214
215void fd_pipe_process_pending(struct fd_pipe *pipe, uint32_t timestamp)
216{
217 struct fd_bo *bo, *tmp;
218
219 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &pipe->pending_list, list[pipe->id]) {
220 struct list_head *list = &bo->list[pipe->id];
221 if (bo->timestamp[pipe->id] > timestamp)
222 return;
223 list_delinit(list);
224 bo->timestamp[pipe->id] = 0;
225 fd_bo_del(bo);
226 }
227}
diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h
new file mode 100644
index 00000000..aa71b564
--- /dev/null
+++ b/freedreno/freedreno_priv.h
@@ -0,0 +1,117 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#ifndef FREEDRENO_PRIV_H_
30#define FREEDRENO_PRIV_H_
31
32#include <stdlib.h>
33#include <errno.h>
34#include <string.h>
35#include <unistd.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <sys/ioctl.h>
39#include <sys/mman.h>
40
41#include "xf86drm.h"
42#include "xf86atomic.h"
43
44#include "list.h"
45
46#include "freedreno_drmif.h"
47#include "msm_kgsl.h"
48#include "kgsl_drm.h"
49
50struct fd_device {
51 int fd;
52};
53
54struct fd_pipe {
55 struct fd_device *dev;
56 enum fd_pipe_id id;
57 int fd;
58 uint32_t drawctxt_id;
59
60 /* device properties: */
61 struct kgsl_version version;
62 struct kgsl_devinfo devinfo;
63
64 /* list of bo's that are referenced in ringbuffer but not
65 * submitted yet:
66 */
67 struct list_head submit_list;
68
69 /* list of bo's that have been submitted but timestamp has
70 * not passed yet (so still ref'd in active cmdstream)
71 */
72 struct list_head pending_list;
73};
74
75void fd_pipe_add_submit(struct fd_pipe *pipe, struct fd_bo *bo);
76void fd_pipe_process_submit(struct fd_pipe *pipe, uint32_t timestamp);
77void fd_pipe_process_pending(struct fd_pipe *pipe, uint32_t timestamp);
78
79struct fd_bo {
80 struct fd_device *dev;
81 uint32_t size;
82 uint32_t handle;
83 uint32_t name;
84 uint32_t gpuaddr;
85 void *map;
86 uint64_t offset;
87 /* timestamp (per pipe) for bo's in a pipe's pending_list: */
88 uint32_t timestamp[FD_PIPE_MAX];
89 /* list-node for pipe's submit_list or pending_list */
90 struct list_head list[FD_PIPE_MAX];
91 atomic_t refcnt;
92};
93
94/* not exposed publicly, because won't be needed when we have
95 * a proper kernel driver
96 */
97uint32_t fd_bo_gpuaddr(struct fd_bo *bo, uint32_t offset);
98
99#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1))
100#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
101
102#define enable_debug 1 /* TODO make dynamic */
103
104#define INFO_MSG(fmt, ...) \
105 do { drmMsg("[I] "fmt " (%s:%d)\n", \
106 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
107#define DEBUG_MSG(fmt, ...) \
108 do if (enable_debug) { drmMsg("[D] "fmt " (%s:%d)\n", \
109 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
110#define WARN_MSG(fmt, ...) \
111 do { drmMsg("[W] "fmt " (%s:%d)\n", \
112 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
113#define ERROR_MSG(fmt, ...) \
114 do { drmMsg("[E] " fmt " (%s:%d)\n", \
115 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
116
117#endif /* FREEDRENO_PRIV_H_ */
diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c
new file mode 100644
index 00000000..822412a9
--- /dev/null
+++ b/freedreno/freedreno_ringbuffer.c
@@ -0,0 +1,249 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#include "freedreno_drmif.h"
30#include "freedreno_priv.h"
31#include "freedreno_ringbuffer.h"
32
33
34/* because kgsl tries to validate the gpuaddr on kernel side in ISSUEIBCMDS,
35 * we can't use normal gem bo's for ringbuffer.. someday the kernel part
36 * needs to be reworked into a single sane drm driver :-/
37 */
38struct fd_rb_bo {
39 struct fd_pipe *pipe;
40 void *hostptr;
41 uint32_t gpuaddr;
42 uint32_t size;
43};
44
45struct fd_ringmarker {
46 struct fd_ringbuffer *ring;
47 uint32_t *cur;
48};
49
50static void fd_rb_bo_del(struct fd_rb_bo *bo)
51{
52 struct kgsl_sharedmem_free req = {
53 .gpuaddr = bo->gpuaddr,
54 };
55 int ret;
56
57 munmap(bo->hostptr, bo->size);
58
59 ret = ioctl(bo->pipe->fd, IOCTL_KGSL_SHAREDMEM_FREE, &req);
60 if (ret) {
61 ERROR_MSG("sharedmem free failed: %s", strerror(errno));
62 }
63
64 free(bo);
65}
66
67static struct fd_rb_bo * fd_rb_bo_new(struct fd_pipe *pipe, uint32_t size)
68{
69 struct fd_rb_bo *bo;
70 struct kgsl_gpumem_alloc req = {
71 .size = ALIGN(size, 4096),
72 .flags = KGSL_MEMFLAGS_GPUREADONLY,
73 };
74 int ret;
75
76 bo = calloc(1, sizeof(*bo));
77 if (!bo) {
78 ERROR_MSG("allocation failed");
79 return NULL;
80 }
81 ret = ioctl(pipe->fd, IOCTL_KGSL_GPUMEM_ALLOC, &req);
82 if (ret) {
83 ERROR_MSG("gpumem allocation failed: %s", strerror(errno));
84 goto fail;
85 }
86
87 bo->pipe = pipe;
88 bo->gpuaddr = req.gpuaddr;
89 bo->size = size;
90 bo->hostptr = mmap(NULL, size, PROT_WRITE|PROT_READ,
91 MAP_SHARED, pipe->fd, req.gpuaddr);
92
93 return bo;
94fail:
95 if (bo)
96 fd_rb_bo_del(bo);
97 return NULL;
98}
99
100struct fd_ringbuffer * fd_ringbuffer_new(struct fd_pipe *pipe,
101 uint32_t size)
102{
103 struct fd_ringbuffer *ring = NULL;
104
105 ring = calloc(1, sizeof(*ring));
106 if (!ring) {
107 ERROR_MSG("allocation failed");
108 goto fail;
109 }
110
111 ring->bo = fd_rb_bo_new(pipe, size);
112 if (!ring->bo) {
113 ERROR_MSG("ringbuffer allocation failed");
114 goto fail;
115 }
116
117 ring->size = size;
118 ring->pipe = pipe;
119 ring->start = ring->bo->hostptr;
120 ring->end = &(ring->start[size/4]);
121
122 ring->cur = ring->last_start = ring->start;
123
124 return ring;
125fail:
126 if (ring)
127 fd_ringbuffer_del(ring);
128 return NULL;
129}
130
131void fd_ringbuffer_del(struct fd_ringbuffer *ring)
132{
133 if (ring->bo)
134 fd_rb_bo_del(ring->bo);
135 free(ring);
136}
137
138void fd_ringbuffer_reset(struct fd_ringbuffer *ring)
139{
140 uint32_t *start = ring->start;
141 if (ring->pipe->id == FD_PIPE_2D)
142 start = &ring->start[0x140];
143 ring->cur = ring->last_start = start;
144}
145
146static int flush_impl(struct fd_ringbuffer *ring, uint32_t *last_start)
147{
148 uint32_t offset = (uint8_t *)last_start - (uint8_t *)ring->start;
149 struct kgsl_ibdesc ibdesc = {
150 .gpuaddr = ring->bo->gpuaddr + offset,
151 .hostptr = last_start,
152 .sizedwords = ring->cur - last_start,
153 };
154 struct kgsl_ringbuffer_issueibcmds req = {
155 .drawctxt_id = ring->pipe->drawctxt_id,
156 .ibdesc_addr = (unsigned long)&ibdesc,
157 .numibs = 1,
158 .flags = KGSL_CONTEXT_SUBMIT_IB_LIST,
159 };
160 int ret;
161
162 /* z180_cmdstream_issueibcmds() is made of fail: */
163 if (ring->pipe->id == FD_PIPE_2D) {
164 /* fix up size field in last cmd packet */
165 uint32_t last_size = (uint32_t)(ring->cur - last_start);
166 /* 5 is length of first packet, 2 for the two 7f000000's */
167 last_start[2] = last_size - (5 + 2);
168 ibdesc.gpuaddr = ring->bo->gpuaddr;
169 ibdesc.hostptr = ring->bo->hostptr;
170 ibdesc.sizedwords = 0x145;
171 req.timestamp = (uint32_t)ring->bo->hostptr;
172 }
173
174 do {
175 ret = ioctl(ring->pipe->fd, IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS, &req);
176 } while ((ret == -1) && ((errno == EINTR) || (errno == EAGAIN)));
177 if (ret)
178 ERROR_MSG("issueibcmds failed! %d (%s)", ret, strerror(errno));
179
180 ring->last_timestamp = req.timestamp;
181 ring->last_start = ring->cur;
182
183 fd_pipe_process_submit(ring->pipe, req.timestamp);
184
185 return ret;
186}
187
188/* maybe get rid of this and use fd_ringmarker_flush() from DDX too? */
189int fd_ringbuffer_flush(struct fd_ringbuffer *ring)
190{
191 return flush_impl(ring, ring->last_start);
192}
193
194uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring)
195{
196 return ring->last_timestamp;
197}
198
199void fd_ringbuffer_emit_reloc(struct fd_ringbuffer *ring,
200 struct fd_bo *bo, uint32_t offset, uint32_t or)
201{
202 (*ring->cur++) = fd_bo_gpuaddr(bo, offset) | or;
203 fd_pipe_add_submit(ring->pipe, bo);
204}
205
206void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
207 struct fd_ringmarker *target)
208{
209 (*ring->cur++) = target->ring->bo->gpuaddr +
210 (uint8_t *)target->cur - (uint8_t *)target->ring->start;
211}
212
213struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring)
214{
215 struct fd_ringmarker *marker = NULL;
216
217 marker = calloc(1, sizeof(*marker));
218 if (!marker) {
219 ERROR_MSG("allocation failed");
220 return NULL;
221 }
222
223 marker->ring = ring;
224
225 fd_ringmarker_mark(marker);
226
227 return marker;
228}
229
230void fd_ringmarker_del(struct fd_ringmarker *marker)
231{
232 free(marker);
233}
234
235void fd_ringmarker_mark(struct fd_ringmarker *marker)
236{
237 marker->cur = marker->ring->cur;
238}
239
240uint32_t fd_ringmarker_dwords(struct fd_ringmarker *start,
241 struct fd_ringmarker *end)
242{
243 return end->cur - start->cur;
244}
245
246int fd_ringmarker_flush(struct fd_ringmarker *marker)
247{
248 return flush_impl(marker->ring, marker->cur);
249}
diff --git a/freedreno/freedreno_ringbuffer.h b/freedreno/freedreno_ringbuffer.h
new file mode 100644
index 00000000..4fb668f7
--- /dev/null
+++ b/freedreno/freedreno_ringbuffer.h
@@ -0,0 +1,87 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#ifndef FREEDRENO_RINGBUFFER_H_
30#define FREEDRENO_RINGBUFFER_H_
31
32#include <freedreno_drmif.h>
33
34/* the ringbuffer object is not opaque so that OUT_RING() type stuff
35 * can be inlined. Note that users should not make assumptions about
36 * the size of this struct.. more stuff will be added when we eventually
37 * have a kernel driver that can deal w/ reloc's..
38 */
39
40struct fd_rb_bo;
41struct fd_ringmarker;
42
43struct fd_ringbuffer {
44 int size;
45 uint32_t *cur, *end, *start, *last_start;
46 struct fd_pipe *pipe;
47 struct fd_rb_bo *bo;
48 uint32_t last_timestamp;
49};
50
51/* ringbuffer flush flags:
52 * SAVE_GMEM - GMEM contents not preserved to system memory
53 * in cmds flushed so if there is a context switch after
54 * this flush and before the next one the kernel must
55 * save GMEM contents
56 * SUBMIT_IB_LIST - tbd..
57 */
58#define DRM_FREEDRENO_CONTEXT_SAVE_GMEM 1
59#define DRM_FREEDRENO_CONTEXT_SUBMIT_IB_LIST 4
60
61
62struct fd_ringbuffer * fd_ringbuffer_new(struct fd_pipe *pipe,
63 uint32_t size);
64void fd_ringbuffer_del(struct fd_ringbuffer *ring);
65void fd_ringbuffer_reset(struct fd_ringbuffer *ring);
66int fd_ringbuffer_flush(struct fd_ringbuffer *ring);
67uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring);
68
69static inline void fd_ringbuffer_emit(struct fd_ringbuffer *ring,
70 uint32_t data)
71{
72 (*ring->cur++) = data;
73}
74
75void fd_ringbuffer_emit_reloc(struct fd_ringbuffer *ring,
76 struct fd_bo *bo, uint32_t offset, uint32_t or);
77void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
78 struct fd_ringmarker *target);
79
80struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring);
81void fd_ringmarker_del(struct fd_ringmarker *marker);
82void fd_ringmarker_mark(struct fd_ringmarker *marker);
83uint32_t fd_ringmarker_dwords(struct fd_ringmarker *start,
84 struct fd_ringmarker *end);
85int fd_ringmarker_flush(struct fd_ringmarker *marker);
86
87#endif /* FREEDRENO_RINGBUFFER_H_ */
diff --git a/freedreno/kgsl_drm.h b/freedreno/kgsl_drm.h
new file mode 100644
index 00000000..f1c7f4e2
--- /dev/null
+++ b/freedreno/kgsl_drm.h
@@ -0,0 +1,192 @@
1#ifndef _KGSL_DRM_H_
2#define _KGSL_DRM_H_
3
4#include "drm.h"
5
6#define DRM_KGSL_GEM_CREATE 0x00
7#define DRM_KGSL_GEM_PREP 0x01
8#define DRM_KGSL_GEM_SETMEMTYPE 0x02
9#define DRM_KGSL_GEM_GETMEMTYPE 0x03
10#define DRM_KGSL_GEM_MMAP 0x04
11#define DRM_KGSL_GEM_ALLOC 0x05
12#define DRM_KGSL_GEM_BIND_GPU 0x06
13#define DRM_KGSL_GEM_UNBIND_GPU 0x07
14
15#define DRM_KGSL_GEM_GET_BUFINFO 0x08
16#define DRM_KGSL_GEM_SET_BUFCOUNT 0x09
17#define DRM_KGSL_GEM_SET_ACTIVE 0x0A
18#define DRM_KGSL_GEM_LOCK_HANDLE 0x0B
19#define DRM_KGSL_GEM_UNLOCK_HANDLE 0x0C
20#define DRM_KGSL_GEM_UNLOCK_ON_TS 0x0D
21#define DRM_KGSL_GEM_CREATE_FD 0x0E
22
23#define DRM_IOCTL_KGSL_GEM_CREATE \
24DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE, struct drm_kgsl_gem_create)
25
26#define DRM_IOCTL_KGSL_GEM_PREP \
27DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_PREP, struct drm_kgsl_gem_prep)
28
29#define DRM_IOCTL_KGSL_GEM_SETMEMTYPE \
30DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SETMEMTYPE, \
31struct drm_kgsl_gem_memtype)
32
33#define DRM_IOCTL_KGSL_GEM_GETMEMTYPE \
34DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GETMEMTYPE, \
35struct drm_kgsl_gem_memtype)
36
37#define DRM_IOCTL_KGSL_GEM_MMAP \
38DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_MMAP, struct drm_kgsl_gem_mmap)
39
40#define DRM_IOCTL_KGSL_GEM_ALLOC \
41DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_ALLOC, struct drm_kgsl_gem_alloc)
42
43#define DRM_IOCTL_KGSL_GEM_BIND_GPU \
44DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_BIND_GPU, struct drm_kgsl_gem_bind_gpu)
45
46#define DRM_IOCTL_KGSL_GEM_UNBIND_GPU \
47DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_UNBIND_GPU, \
48struct drm_kgsl_gem_bind_gpu)
49
50#define DRM_IOCTL_KGSL_GEM_GET_BUFINFO \
51DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_BUFINFO, \
52 struct drm_kgsl_gem_bufinfo)
53
54#define DRM_IOCTL_KGSL_GEM_SET_BUFCOUNT \
55DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_BUFCOUNT, \
56 struct drm_kgsl_gem_bufcount)
57
58#define DRM_IOCTL_KGSL_GEM_SET_ACTIVE \
59DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_ACTIVE, \
60 struct drm_kgsl_gem_active)
61
62#define DRM_IOCTL_KGSL_GEM_LOCK_HANDLE \
63DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_LOCK_HANDLE, \
64struct drm_kgsl_gem_lock_handles)
65
66#define DRM_IOCTL_KGSL_GEM_UNLOCK_HANDLE \
67DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_UNLOCK_HANDLE, \
68struct drm_kgsl_gem_unlock_handles)
69
70#define DRM_IOCTL_KGSL_GEM_UNLOCK_ON_TS \
71DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_UNLOCK_ON_TS, \
72struct drm_kgsl_gem_unlock_on_ts)
73
74#define DRM_IOCTL_KGSL_GEM_CREATE_FD \
75DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FD, \
76struct drm_kgsl_gem_create_fd)
77
78/* Maximum number of sub buffers per GEM object */
79#define DRM_KGSL_GEM_MAX_BUFFERS 2
80
81/* Memory types - these define the source and caching policies
82 of the GEM memory chunk */
83
84/* Legacy definitions left for compatability */
85
86#define DRM_KGSL_GEM_TYPE_EBI 0
87#define DRM_KGSL_GEM_TYPE_SMI 1
88#define DRM_KGSL_GEM_TYPE_KMEM 2
89#define DRM_KGSL_GEM_TYPE_KMEM_NOCACHE 3
90#define DRM_KGSL_GEM_TYPE_MEM_MASK 0xF
91
92/* Contiguous memory (PMEM) */
93#define DRM_KGSL_GEM_TYPE_PMEM 0x000100
94
95/* PMEM memory types */
96#define DRM_KGSL_GEM_PMEM_EBI 0x001000
97#define DRM_KGSL_GEM_PMEM_SMI 0x002000
98
99/* Standard paged memory */
100#define DRM_KGSL_GEM_TYPE_MEM 0x010000
101
102/* Caching controls */
103#define DRM_KGSL_GEM_CACHE_NONE 0x000000
104#define DRM_KGSL_GEM_CACHE_WCOMBINE 0x100000
105#define DRM_KGSL_GEM_CACHE_WTHROUGH 0x200000
106#define DRM_KGSL_GEM_CACHE_WBACK 0x400000
107#define DRM_KGSL_GEM_CACHE_WBACKWA 0x800000
108#define DRM_KGSL_GEM_CACHE_MASK 0xF00000
109
110/* FD based objects */
111#define DRM_KGSL_GEM_TYPE_FD_FBMEM 0x1000000
112#define DRM_KGSL_GEM_TYPE_FD_MASK 0xF000000
113
114/* Timestamp types */
115#define DRM_KGSL_GEM_TS_3D 0x00000430
116#define DRM_KGSL_GEM_TS_2D 0x00000180
117
118
119struct drm_kgsl_gem_create {
120 uint32_t size;
121 uint32_t handle;
122};
123
124struct drm_kgsl_gem_prep {
125 uint32_t handle;
126 uint32_t phys;
127 uint64_t offset;
128};
129
130struct drm_kgsl_gem_memtype {
131 uint32_t handle;
132 uint32_t type;
133};
134
135struct drm_kgsl_gem_mmap {
136 uint32_t handle;
137 uint32_t size;
138 uint32_t hostptr;
139 uint64_t offset;
140};
141
142struct drm_kgsl_gem_alloc {
143 uint32_t handle;
144 uint64_t offset;
145};
146
147struct drm_kgsl_gem_bind_gpu {
148 uint32_t handle;
149 uint32_t gpuptr;
150};
151
152struct drm_kgsl_gem_bufinfo {
153 uint32_t handle;
154 uint32_t count;
155 uint32_t active;
156 uint32_t offset[DRM_KGSL_GEM_MAX_BUFFERS];
157 uint32_t gpuaddr[DRM_KGSL_GEM_MAX_BUFFERS];
158};
159
160struct drm_kgsl_gem_bufcount {
161 uint32_t handle;
162 uint32_t bufcount;
163};
164
165struct drm_kgsl_gem_active {
166 uint32_t handle;
167 uint32_t active;
168};
169
170struct drm_kgsl_gem_lock_handles {
171 uint32_t num_handles;
172 uint32_t *handle_list;
173 uint32_t pid;
174 uint32_t lock_id; /* Returned lock id used for unlocking */
175};
176
177struct drm_kgsl_gem_unlock_handles {
178 uint32_t lock_id;
179};
180
181struct drm_kgsl_gem_unlock_on_ts {
182 uint32_t lock_id;
183 uint32_t timestamp; /* This field is a hw generated ts */
184 uint32_t type; /* Which pipe to check for ts generation */
185};
186
187struct drm_kgsl_gem_create_fd {
188 uint32_t fd;
189 uint32_t handle;
190};
191
192#endif
diff --git a/freedreno/libdrm_freedreno.pc.in b/freedreno/libdrm_freedreno.pc.in
new file mode 100644
index 00000000..b736b65a
--- /dev/null
+++ b/freedreno/libdrm_freedreno.pc.in
@@ -0,0 +1,11 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: libdrm_freedreno
7Description: Userspace interface to freedreno kernel DRM services
8Version: @PACKAGE_VERSION@
9Libs: -L${libdir} -ldrm_freedreno
10Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/freedreno
11Requires.private: libdrm
diff --git a/freedreno/list.h b/freedreno/list.h
new file mode 100644
index 00000000..27e0761b
--- /dev/null
+++ b/freedreno/list.h
@@ -0,0 +1,137 @@
1/*
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 */
27
28/**
29 * \file
30 * List macros heavily inspired by the Linux kernel
31 * list handling. No list looping yet.
32 *
33 * Is not threadsafe, so common operations need to
34 * be protected using an external mutex.
35 */
36#ifndef _U_DOUBLE_LIST_H_
37#define _U_DOUBLE_LIST_H_
38
39#include <stddef.h>
40
41struct list_head
42{
43 struct list_head *prev;
44 struct list_head *next;
45};
46
47static inline void list_inithead(struct list_head *item)
48{
49 item->prev = item;
50 item->next = item;
51}
52
53static inline void list_add(struct list_head *item, struct list_head *list)
54{
55 item->prev = list;
56 item->next = list->next;
57 list->next->prev = item;
58 list->next = item;
59}
60
61static inline void list_addtail(struct list_head *item, struct list_head *list)
62{
63 item->next = list;
64 item->prev = list->prev;
65 list->prev->next = item;
66 list->prev = item;
67}
68
69static inline void list_replace(struct list_head *from, struct list_head *to)
70{
71 to->prev = from->prev;
72 to->next = from->next;
73 from->next->prev = to;
74 from->prev->next = to;
75}
76
77static inline void list_del(struct list_head *item)
78{
79 item->prev->next = item->next;
80 item->next->prev = item->prev;
81}
82
83static inline void list_delinit(struct list_head *item)
84{
85 item->prev->next = item->next;
86 item->next->prev = item->prev;
87 item->next = item;
88 item->prev = item;
89}
90
91#define LIST_INITHEAD(__item) list_inithead(__item)
92#define LIST_ADD(__item, __list) list_add(__item, __list)
93#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list)
94#define LIST_REPLACE(__from, __to) list_replace(__from, __to)
95#define LIST_DEL(__item) list_del(__item)
96#define LIST_DELINIT(__item) list_delinit(__item)
97
98#define LIST_ENTRY(__type, __item, __field) \
99 ((__type *)(((char *)(__item)) - offsetof(__type, __field)))
100
101#define LIST_IS_EMPTY(__list) \
102 ((__list)->next == (__list))
103
104#ifndef container_of
105#define container_of(ptr, sample, member) \
106 (void *)((char *)(ptr) \
107 - ((char *)&(sample)->member - (char *)(sample)))
108#endif
109
110#define LIST_FOR_EACH_ENTRY(pos, head, member) \
111 for (pos = container_of((head)->next, pos, member); \
112 &pos->member != (head); \
113 pos = container_of(pos->member.next, pos, member))
114
115#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \
116 for (pos = container_of((head)->next, pos, member), \
117 storage = container_of(pos->member.next, pos, member); \
118 &pos->member != (head); \
119 pos = storage, storage = container_of(storage->member.next, storage, member))
120
121#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \
122 for (pos = container_of((head)->prev, pos, member), \
123 storage = container_of(pos->member.prev, pos, member); \
124 &pos->member != (head); \
125 pos = storage, storage = container_of(storage->member.prev, storage, member))
126
127#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \
128 for (pos = container_of((start), pos, member); \
129 &pos->member != (head); \
130 pos = container_of(pos->member.next, pos, member))
131
132#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \
133 for (pos = container_of((start), pos, member); \
134 &pos->member != (head); \
135 pos = container_of(pos->member.prev, pos, member))
136
137#endif /*_U_DOUBLE_LIST_H_*/
diff --git a/freedreno/msm_kgsl.h b/freedreno/msm_kgsl.h
new file mode 100644
index 00000000..e67190f0
--- /dev/null
+++ b/freedreno/msm_kgsl.h
@@ -0,0 +1,519 @@
1#ifndef _MSM_KGSL_H
2#define _MSM_KGSL_H
3
4#define KGSL_VERSION_MAJOR 3
5#define KGSL_VERSION_MINOR 11
6
7/*context flags */
8#define KGSL_CONTEXT_SAVE_GMEM 0x00000001
9#define KGSL_CONTEXT_NO_GMEM_ALLOC 0x00000002
10#define KGSL_CONTEXT_SUBMIT_IB_LIST 0x00000004
11#define KGSL_CONTEXT_CTX_SWITCH 0x00000008
12#define KGSL_CONTEXT_PREAMBLE 0x00000010
13#define KGSL_CONTEXT_TRASH_STATE 0x00000020
14#define KGSL_CONTEXT_PER_CONTEXT_TS 0x00000040
15
16#define KGSL_CONTEXT_INVALID 0xffffffff
17
18/* Memory allocayion flags */
19#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000
20
21/* generic flag values */
22#define KGSL_FLAGS_NORMALMODE 0x00000000
23#define KGSL_FLAGS_SAFEMODE 0x00000001
24#define KGSL_FLAGS_INITIALIZED0 0x00000002
25#define KGSL_FLAGS_INITIALIZED 0x00000004
26#define KGSL_FLAGS_STARTED 0x00000008
27#define KGSL_FLAGS_ACTIVE 0x00000010
28#define KGSL_FLAGS_RESERVED0 0x00000020
29#define KGSL_FLAGS_RESERVED1 0x00000040
30#define KGSL_FLAGS_RESERVED2 0x00000080
31#define KGSL_FLAGS_SOFT_RESET 0x00000100
32#define KGSL_FLAGS_PER_CONTEXT_TIMESTAMPS 0x00000200
33
34/* Clock flags to show which clocks should be controled by a given platform */
35#define KGSL_CLK_SRC 0x00000001
36#define KGSL_CLK_CORE 0x00000002
37#define KGSL_CLK_IFACE 0x00000004
38#define KGSL_CLK_MEM 0x00000008
39#define KGSL_CLK_MEM_IFACE 0x00000010
40#define KGSL_CLK_AXI 0x00000020
41
42/*
43 * Reset status values for context
44 */
45enum kgsl_ctx_reset_stat {
46 KGSL_CTX_STAT_NO_ERROR = 0x00000000,
47 KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT = 0x00000001,
48 KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT = 0x00000002,
49 KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT = 0x00000003
50};
51
52#define KGSL_MAX_PWRLEVELS 5
53
54#define KGSL_CONVERT_TO_MBPS(val) \
55 (val*1000*1000U)
56
57/* device id */
58enum kgsl_deviceid {
59 KGSL_DEVICE_3D0 = 0x00000000,
60 KGSL_DEVICE_2D0 = 0x00000001,
61 KGSL_DEVICE_2D1 = 0x00000002,
62 KGSL_DEVICE_MAX = 0x00000003
63};
64
65enum kgsl_user_mem_type {
66 KGSL_USER_MEM_TYPE_PMEM = 0x00000000,
67 KGSL_USER_MEM_TYPE_ASHMEM = 0x00000001,
68 KGSL_USER_MEM_TYPE_ADDR = 0x00000002,
69 KGSL_USER_MEM_TYPE_ION = 0x00000003,
70 KGSL_USER_MEM_TYPE_MAX = 0x00000004,
71};
72
73struct kgsl_devinfo {
74
75 unsigned int device_id;
76 /* chip revision id
77 * coreid:8 majorrev:8 minorrev:8 patch:8
78 */
79 unsigned int chip_id;
80 unsigned int mmu_enabled;
81 unsigned int gmem_gpubaseaddr;
82 /*
83 * This field contains the adreno revision
84 * number 200, 205, 220, etc...
85 */
86 unsigned int gpu_id;
87 unsigned int gmem_sizebytes;
88};
89
90/* this structure defines the region of memory that can be mmap()ed from this
91 driver. The timestamp fields are volatile because they are written by the
92 GPU
93*/
94struct kgsl_devmemstore {
95 volatile unsigned int soptimestamp;
96 unsigned int sbz;
97 volatile unsigned int eoptimestamp;
98 unsigned int sbz2;
99 volatile unsigned int ts_cmp_enable;
100 unsigned int sbz3;
101 volatile unsigned int ref_wait_ts;
102 unsigned int sbz4;
103 unsigned int current_context;
104 unsigned int sbz5;
105};
106
107#define KGSL_MEMSTORE_OFFSET(ctxt_id, field) \
108 ((ctxt_id)*sizeof(struct kgsl_devmemstore) + \
109 offsetof(struct kgsl_devmemstore, field))
110
111/* timestamp id*/
112enum kgsl_timestamp_type {
113 KGSL_TIMESTAMP_CONSUMED = 0x00000001, /* start-of-pipeline timestamp */
114 KGSL_TIMESTAMP_RETIRED = 0x00000002, /* end-of-pipeline timestamp*/
115 KGSL_TIMESTAMP_QUEUED = 0x00000003,
116};
117
118/* property types - used with kgsl_device_getproperty */
119enum kgsl_property_type {
120 KGSL_PROP_DEVICE_INFO = 0x00000001,
121 KGSL_PROP_DEVICE_SHADOW = 0x00000002,
122 KGSL_PROP_DEVICE_POWER = 0x00000003,
123 KGSL_PROP_SHMEM = 0x00000004,
124 KGSL_PROP_SHMEM_APERTURES = 0x00000005,
125 KGSL_PROP_MMU_ENABLE = 0x00000006,
126 KGSL_PROP_INTERRUPT_WAITS = 0x00000007,
127 KGSL_PROP_VERSION = 0x00000008,
128 KGSL_PROP_GPU_RESET_STAT = 0x00000009,
129 KGSL_PROP_PWRCTRL = 0x0000000E,
130};
131
132struct kgsl_shadowprop {
133 unsigned int gpuaddr;
134 unsigned int size;
135 unsigned int flags; /* contains KGSL_FLAGS_ values */
136};
137
138struct kgsl_pwrlevel {
139 unsigned int gpu_freq;
140 unsigned int bus_freq;
141 unsigned int io_fraction;
142};
143
144struct kgsl_version {
145 unsigned int drv_major;
146 unsigned int drv_minor;
147 unsigned int dev_major;
148 unsigned int dev_minor;
149};
150
151#ifdef __KERNEL__
152
153#define KGSL_3D0_REG_MEMORY "kgsl_3d0_reg_memory"
154#define KGSL_3D0_IRQ "kgsl_3d0_irq"
155#define KGSL_2D0_REG_MEMORY "kgsl_2d0_reg_memory"
156#define KGSL_2D0_IRQ "kgsl_2d0_irq"
157#define KGSL_2D1_REG_MEMORY "kgsl_2d1_reg_memory"
158#define KGSL_2D1_IRQ "kgsl_2d1_irq"
159
160enum kgsl_iommu_context_id {
161 KGSL_IOMMU_CONTEXT_USER = 0,
162 KGSL_IOMMU_CONTEXT_PRIV = 1,
163};
164
165struct kgsl_iommu_ctx {
166 const char *iommu_ctx_name;
167 enum kgsl_iommu_context_id ctx_id;
168};
169
170struct kgsl_device_iommu_data {
171 const struct kgsl_iommu_ctx *iommu_ctxs;
172 int iommu_ctx_count;
173 unsigned int physstart;
174 unsigned int physend;
175};
176
177struct kgsl_device_platform_data {
178 struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
179 int init_level;
180 int num_levels;
181 int (*set_grp_async)(void);
182 unsigned int idle_timeout;
183 bool strtstp_sleepwake;
184 unsigned int nap_allowed;
185 unsigned int clk_map;
186 unsigned int idle_needed;
187 struct msm_bus_scale_pdata *bus_scale_table;
188 struct kgsl_device_iommu_data *iommu_data;
189 int iommu_count;
190 struct msm_dcvs_core_info *core_info;
191};
192
193#endif
194
195/* structure holds list of ibs */
196struct kgsl_ibdesc {
197 unsigned int gpuaddr;
198 void *hostptr;
199 unsigned int sizedwords;
200 unsigned int ctrl;
201};
202
203/* ioctls */
204#define KGSL_IOC_TYPE 0x09
205
206/* get misc info about the GPU
207 type should be a value from enum kgsl_property_type
208 value points to a structure that varies based on type
209 sizebytes is sizeof() that structure
210 for KGSL_PROP_DEVICE_INFO, use struct kgsl_devinfo
211 this structure contaings hardware versioning info.
212 for KGSL_PROP_DEVICE_SHADOW, use struct kgsl_shadowprop
213 this is used to find mmap() offset and sizes for mapping
214 struct kgsl_memstore into userspace.
215*/
216struct kgsl_device_getproperty {
217 unsigned int type;
218 void *value;
219 unsigned int sizebytes;
220};
221
222#define IOCTL_KGSL_DEVICE_GETPROPERTY \
223 _IOWR(KGSL_IOC_TYPE, 0x2, struct kgsl_device_getproperty)
224
225/* IOCTL_KGSL_DEVICE_READ (0x3) - removed 03/2012
226 */
227
228/* block until the GPU has executed past a given timestamp
229 * timeout is in milliseconds.
230 */
231struct kgsl_device_waittimestamp {
232 unsigned int timestamp;
233 unsigned int timeout;
234};
235
236#define IOCTL_KGSL_DEVICE_WAITTIMESTAMP \
237 _IOW(KGSL_IOC_TYPE, 0x6, struct kgsl_device_waittimestamp)
238
239struct kgsl_device_waittimestamp_ctxtid {
240 unsigned int context_id;
241 unsigned int timestamp;
242 unsigned int timeout;
243};
244
245#define IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID \
246 _IOW(KGSL_IOC_TYPE, 0x7, struct kgsl_device_waittimestamp_ctxtid)
247
248/* issue indirect commands to the GPU.
249 * drawctxt_id must have been created with IOCTL_KGSL_DRAWCTXT_CREATE
250 * ibaddr and sizedwords must specify a subset of a buffer created
251 * with IOCTL_KGSL_SHAREDMEM_FROM_PMEM
252 * flags may be a mask of KGSL_CONTEXT_ values
253 * timestamp is a returned counter value which can be passed to
254 * other ioctls to determine when the commands have been executed by
255 * the GPU.
256 */
257struct kgsl_ringbuffer_issueibcmds {
258 unsigned int drawctxt_id;
259 unsigned int ibdesc_addr;
260 unsigned int numibs;
261 unsigned int timestamp; /*output param */
262 unsigned int flags;
263};
264
265#define IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS \
266 _IOWR(KGSL_IOC_TYPE, 0x10, struct kgsl_ringbuffer_issueibcmds)
267
268/* read the most recently executed timestamp value
269 * type should be a value from enum kgsl_timestamp_type
270 */
271struct kgsl_cmdstream_readtimestamp {
272 unsigned int type;
273 unsigned int timestamp; /*output param */
274};
275
276#define IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_OLD \
277 _IOR(KGSL_IOC_TYPE, 0x11, struct kgsl_cmdstream_readtimestamp)
278
279#define IOCTL_KGSL_CMDSTREAM_READTIMESTAMP \
280 _IOWR(KGSL_IOC_TYPE, 0x11, struct kgsl_cmdstream_readtimestamp)
281
282/* free memory when the GPU reaches a given timestamp.
283 * gpuaddr specify a memory region created by a
284 * IOCTL_KGSL_SHAREDMEM_FROM_PMEM call
285 * type should be a value from enum kgsl_timestamp_type
286 */
287struct kgsl_cmdstream_freememontimestamp {
288 unsigned int gpuaddr;
289 unsigned int type;
290 unsigned int timestamp;
291};
292
293#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP \
294 _IOW(KGSL_IOC_TYPE, 0x12, struct kgsl_cmdstream_freememontimestamp)
295
296/* Previous versions of this header had incorrectly defined
297 IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP as a read-only ioctl instead
298 of a write only ioctl. To ensure binary compatability, the following
299 #define will be used to intercept the incorrect ioctl
300*/
301
302#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_OLD \
303 _IOR(KGSL_IOC_TYPE, 0x12, struct kgsl_cmdstream_freememontimestamp)
304
305/* create a draw context, which is used to preserve GPU state.
306 * The flags field may contain a mask KGSL_CONTEXT_* values
307 */
308struct kgsl_drawctxt_create {
309 unsigned int flags;
310 unsigned int drawctxt_id; /*output param */
311};
312
313#define IOCTL_KGSL_DRAWCTXT_CREATE \
314 _IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create)
315
316/* destroy a draw context */
317struct kgsl_drawctxt_destroy {
318 unsigned int drawctxt_id;
319};
320
321#define IOCTL_KGSL_DRAWCTXT_DESTROY \
322 _IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy)
323
324/* add a block of pmem, fb, ashmem or user allocated address
325 * into the GPU address space */
326struct kgsl_map_user_mem {
327 int fd;
328 unsigned int gpuaddr; /*output param */
329 unsigned int len;
330 unsigned int offset;
331 unsigned int hostptr; /*input param */
332 enum kgsl_user_mem_type memtype;
333 unsigned int reserved; /* May be required to add
334 params for another mem type */
335};
336
337#define IOCTL_KGSL_MAP_USER_MEM \
338 _IOWR(KGSL_IOC_TYPE, 0x15, struct kgsl_map_user_mem)
339
340struct kgsl_cmdstream_readtimestamp_ctxtid {
341 unsigned int context_id;
342 unsigned int type;
343 unsigned int timestamp; /*output param */
344};
345
346#define IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID \
347 _IOWR(KGSL_IOC_TYPE, 0x16, struct kgsl_cmdstream_readtimestamp_ctxtid)
348
349struct kgsl_cmdstream_freememontimestamp_ctxtid {
350 unsigned int context_id;
351 unsigned int gpuaddr;
352 unsigned int type;
353 unsigned int timestamp;
354};
355
356#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID \
357 _IOW(KGSL_IOC_TYPE, 0x17, \
358 struct kgsl_cmdstream_freememontimestamp_ctxtid)
359
360/* add a block of pmem or fb into the GPU address space */
361struct kgsl_sharedmem_from_pmem {
362 int pmem_fd;
363 unsigned int gpuaddr; /*output param */
364 unsigned int len;
365 unsigned int offset;
366};
367
368#define IOCTL_KGSL_SHAREDMEM_FROM_PMEM \
369 _IOWR(KGSL_IOC_TYPE, 0x20, struct kgsl_sharedmem_from_pmem)
370
371/* remove memory from the GPU's address space */
372struct kgsl_sharedmem_free {
373 unsigned int gpuaddr;
374};
375
376#define IOCTL_KGSL_SHAREDMEM_FREE \
377 _IOW(KGSL_IOC_TYPE, 0x21, struct kgsl_sharedmem_free)
378
379struct kgsl_cff_user_event {
380 unsigned char cff_opcode;
381 unsigned int op1;
382 unsigned int op2;
383 unsigned int op3;
384 unsigned int op4;
385 unsigned int op5;
386 unsigned int __pad[2];
387};
388
389#define IOCTL_KGSL_CFF_USER_EVENT \
390 _IOW(KGSL_IOC_TYPE, 0x31, struct kgsl_cff_user_event)
391
392struct kgsl_gmem_desc {
393 unsigned int x;
394 unsigned int y;
395 unsigned int width;
396 unsigned int height;
397 unsigned int pitch;
398};
399
400struct kgsl_buffer_desc {
401 void *hostptr;
402 unsigned int gpuaddr;
403 int size;
404 unsigned int format;
405 unsigned int pitch;
406 unsigned int enabled;
407};
408
409struct kgsl_bind_gmem_shadow {
410 unsigned int drawctxt_id;
411 struct kgsl_gmem_desc gmem_desc;
412 unsigned int shadow_x;
413 unsigned int shadow_y;
414 struct kgsl_buffer_desc shadow_buffer;
415 unsigned int buffer_id;
416};
417
418#define IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW \
419 _IOW(KGSL_IOC_TYPE, 0x22, struct kgsl_bind_gmem_shadow)
420
421/* add a block of memory into the GPU address space */
422struct kgsl_sharedmem_from_vmalloc {
423 unsigned int gpuaddr; /*output param */
424 unsigned int hostptr;
425 unsigned int flags;
426};
427
428#define IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC \
429 _IOWR(KGSL_IOC_TYPE, 0x23, struct kgsl_sharedmem_from_vmalloc)
430
431#define IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE \
432 _IOW(KGSL_IOC_TYPE, 0x24, struct kgsl_sharedmem_free)
433
434struct kgsl_drawctxt_set_bin_base_offset {
435 unsigned int drawctxt_id;
436 unsigned int offset;
437};
438
439#define IOCTL_KGSL_DRAWCTXT_SET_BIN_BASE_OFFSET \
440 _IOW(KGSL_IOC_TYPE, 0x25, struct kgsl_drawctxt_set_bin_base_offset)
441
442enum kgsl_cmdwindow_type {
443 KGSL_CMDWINDOW_MIN = 0x00000000,
444 KGSL_CMDWINDOW_2D = 0x00000000,
445 KGSL_CMDWINDOW_3D = 0x00000001, /* legacy */
446 KGSL_CMDWINDOW_MMU = 0x00000002,
447 KGSL_CMDWINDOW_ARBITER = 0x000000FF,
448 KGSL_CMDWINDOW_MAX = 0x000000FF,
449};
450
451/* write to the command window */
452struct kgsl_cmdwindow_write {
453 enum kgsl_cmdwindow_type target;
454 unsigned int addr;
455 unsigned int data;
456};
457
458#define IOCTL_KGSL_CMDWINDOW_WRITE \
459 _IOW(KGSL_IOC_TYPE, 0x2e, struct kgsl_cmdwindow_write)
460
461struct kgsl_gpumem_alloc {
462 unsigned long gpuaddr;
463 size_t size;
464 unsigned int flags;
465};
466
467#define IOCTL_KGSL_GPUMEM_ALLOC \
468 _IOWR(KGSL_IOC_TYPE, 0x2f, struct kgsl_gpumem_alloc)
469
470struct kgsl_cff_syncmem {
471 unsigned int gpuaddr;
472 unsigned int len;
473 unsigned int __pad[2]; /* For future binary compatibility */
474};
475
476#define IOCTL_KGSL_CFF_SYNCMEM \
477 _IOW(KGSL_IOC_TYPE, 0x30, struct kgsl_cff_syncmem)
478
479/*
480 * A timestamp event allows the user space to register an action following an
481 * expired timestamp.
482 */
483
484struct kgsl_timestamp_event {
485 int type; /* Type of event (see list below) */
486 unsigned int timestamp; /* Timestamp to trigger event on */
487 unsigned int context_id; /* Context for the timestamp */
488 void *priv; /* Pointer to the event specific blob */
489 size_t len; /* Size of the event specific blob */
490};
491
492#define IOCTL_KGSL_TIMESTAMP_EVENT \
493 _IOW(KGSL_IOC_TYPE, 0x31, struct kgsl_timestamp_event)
494
495/* A genlock timestamp event releases an existing lock on timestamp expire */
496
497#define KGSL_TIMESTAMP_EVENT_GENLOCK 1
498
499struct kgsl_timestamp_event_genlock {
500 int handle; /* Handle of the genlock lock to release */
501};
502
503/*
504 * Set a property within the kernel. Uses the same structure as
505 * IOCTL_KGSL_GETPROPERTY
506 */
507
508#define IOCTL_KGSL_SETPROPERTY \
509 _IOW(KGSL_IOC_TYPE, 0x32, struct kgsl_device_getproperty)
510
511#ifdef __KERNEL__
512#ifdef CONFIG_MSM_KGSL_DRM
513int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
514 unsigned long *len);
515#else
516#define kgsl_gem_obj_addr(...) 0
517#endif
518#endif
519#endif /* _MSM_KGSL_H */