summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imagination/pvr_gem.h
blob: e0e5ea509a2e88a437b8d241ea13c7bab2220f56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
/* Copyright (c) 2023 Imagination Technologies Ltd. */

#ifndef PVR_GEM_H
#define PVR_GEM_H

#include "pvr_rogue_heap_config.h"
#include "pvr_rogue_meta.h"

#include <uapi/drm/pvr_drm.h>

#include <drm/drm_gem.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_mm.h>

#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/const.h>
#include <linux/compiler_attributes.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/refcount.h>
#include <linux/scatterlist.h>
#include <linux/sizes.h>
#include <linux/types.h>

/* Forward declaration from "pvr_device.h". */
struct pvr_device;
struct pvr_file;

/**
 * DOC: Flags for DRM_IOCTL_PVR_CREATE_BO (kernel-only)
 *
 * Kernel-only values allowed in &pvr_gem_object->flags. The majority of options
 * for this field are specified in the UAPI header "pvr_drm.h" with a
 * DRM_PVR_BO_ prefix. To distinguish these internal options (which must exist
 * in ranges marked as "reserved" in the UAPI header), we drop the DRM prefix.
 * The public options should be used directly, DRM prefix and all.
 *
 * To avoid potentially confusing gaps in the UAPI options, these kernel-only
 * options are specified "in reverse", starting at bit 63.
 *
 * We use "reserved" to refer to bits defined here and not exposed in the UAPI.
 * Bits not defined anywhere are "undefined".
 *
 * CPU mapping options
 *    :PVR_BO_CPU_CACHED: By default, all GEM objects are mapped write-combined on the CPU. Set this
 *       flag to override this behaviour and map the object cached.
 *
 * Firmware options
 *    :PVR_BO_FW_NO_CLEAR_ON_RESET: By default, all FW objects are cleared and reinitialised on hard
 *       reset. Set this flag to override this behaviour and preserve buffer contents on reset.
 */
#define PVR_BO_CPU_CACHED BIT_ULL(63)

#define PVR_BO_FW_NO_CLEAR_ON_RESET BIT_ULL(62)

#define PVR_BO_KERNEL_FLAGS_MASK (PVR_BO_CPU_CACHED | PVR_BO_FW_NO_CLEAR_ON_RESET)

/* Bits 61..3 are undefined. */
/* Bits 2..0 are defined in the UAPI. */

/* Other utilities. */
#define PVR_BO_UNDEFINED_MASK ~(PVR_BO_KERNEL_FLAGS_MASK | DRM_PVR_BO_FLAGS_MASK)

/*
 * All firmware-mapped memory uses (mostly) the same flags. Specifically,
 * firmware-mapped memory should be:
 *  * Read/write on the device,
 *  * Read/write on the CPU, and
 *  * Write-combined on the CPU.
 *
 * The only variation is in caching on the device.
 */
#define PVR_BO_FW_FLAGS_DEVICE_CACHED (ULL(0))
#define PVR_BO_FW_FLAGS_DEVICE_UNCACHED DRM_PVR_BO_BYPASS_DEVICE_CACHE

/**
 * struct pvr_gem_object - powervr-specific wrapper for &struct drm_gem_object
 */
struct pvr_gem_object {
	/**
	 * @base: The underlying &struct drm_gem_shmem_object.
	 *
	 * Do not access this member directly, instead call
	 * shem_gem_from_pvr_gem().
	 */
	struct drm_gem_shmem_object base;

	/**
	 * @flags: Options set at creation-time. Some of these options apply to
	 * the creation operation itself (which are stored here for reference)
	 * with the remainder used for mapping options to both the device and
	 * CPU. These are used every time this object is mapped, but may be
	 * changed after creation.
	 *
	 * Must be a combination of DRM_PVR_BO_* and/or PVR_BO_* flags.
	 *
	 * .. note::
	 *
	 *    This member is declared const to indicate that none of these
	 *    options may change or be changed throughout the object's
	 *    lifetime.
	 */
	u64 flags;

};

static_assert(offsetof(struct pvr_gem_object, base) == 0,
	      "offsetof(struct pvr_gem_object, base) not zero");

#define shmem_gem_from_pvr_gem(pvr_obj) (&(pvr_obj)->base)

#define shmem_gem_to_pvr_gem(shmem_obj) container_of_const(shmem_obj, struct pvr_gem_object, base)

#define gem_from_pvr_gem(pvr_obj) (&(pvr_obj)->base.base)

#define gem_to_pvr_gem(gem_obj) container_of_const(gem_obj, struct pvr_gem_object, base.base)

/* Functions defined in pvr_gem.c */

struct drm_gem_object *pvr_gem_create_object(struct drm_device *drm_dev, size_t size);

struct pvr_gem_object *pvr_gem_object_create(struct pvr_device *pvr_dev,
					     size_t size, u64 flags);

int pvr_gem_object_into_handle(struct pvr_gem_object *pvr_obj,
			       struct pvr_file *pvr_file, u32 *handle);
struct pvr_gem_object *pvr_gem_object_from_handle(struct pvr_file *pvr_file,
						  u32 handle);

static __always_inline struct sg_table *
pvr_gem_object_get_pages_sgt(struct pvr_gem_object *pvr_obj)
{
	return drm_gem_shmem_get_pages_sgt(shmem_gem_from_pvr_gem(pvr_obj));
}

void *pvr_gem_object_vmap(struct pvr_gem_object *pvr_obj);
void pvr_gem_object_vunmap(struct pvr_gem_object *pvr_obj);

int pvr_gem_get_dma_addr(struct pvr_gem_object *pvr_obj, u32 offset,
			 dma_addr_t *dma_addr_out);

/**
 * pvr_gem_object_get() - Acquire reference on pvr_gem_object
 * @pvr_obj: Pointer to object to acquire reference on.
 */
static __always_inline void
pvr_gem_object_get(struct pvr_gem_object *pvr_obj)
{
	drm_gem_object_get(gem_from_pvr_gem(pvr_obj));
}

/**
 * pvr_gem_object_put() - Release reference on pvr_gem_object
 * @pvr_obj: Pointer to object to release reference on.
 */
static __always_inline void
pvr_gem_object_put(struct pvr_gem_object *pvr_obj)
{
	drm_gem_object_put(gem_from_pvr_gem(pvr_obj));
}

static __always_inline size_t
pvr_gem_object_size(struct pvr_gem_object *pvr_obj)
{
	return gem_from_pvr_gem(pvr_obj)->size;
}

#endif /* PVR_GEM_H */