summaryrefslogtreecommitdiff
path: root/driver/product/kernel/drivers/gpu/drm/pl111/pl111_drm.h
blob: 64d87b60ff6db7fa3e823f3e66c97e3c9021b5ff (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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
 *
 * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained
 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 */



#ifndef _PL111_DRM_H_
#define _PL111_DRM_H_

#define DRIVER_AUTHOR    "ARM Ltd."
#define DRIVER_NAME      "pl111_drm"
#define DRIVER_DESC      "DRM module for PL111"
#define DRIVER_LICENCE   "GPL"
#define DRIVER_ALIAS     "platform:pl111_drm"
#define DRIVER_DATE      "20101111"
#define DRIVER_VERSION   "0.2"
#define DRIVER_MAJOR      2
#define DRIVER_MINOR      1
#define DRIVER_PATCHLEVEL 1

/*
 * Number of flips allowed in flight at any one time. Any more flips requested
 * beyond this value will cause the caller to block until earlier flips have
 * completed.
 *
 * For performance reasons, this must be greater than the number of buffers
 * used in the rendering pipeline. Note that the rendering pipeline can contain
 * different types of buffer, e.g.:
 * - 2 final framebuffers
 * - >2 geometry buffers for GPU use-cases
 * - >2 vertex buffers for GPU use-cases
 *
 * For example, a system using 5 geometry buffers could have 5 flips in flight,
 * and so NR_FLIPS_IN_FLIGHT_THRESHOLD must be 5 or greater.
 *
 * Whilst there may be more intermediate buffers (such as vertex/geometry) than
 * final framebuffers, KDS is used to ensure that GPU rendering waits for the
 * next off-screen buffer, so it doesn't overwrite an on-screen buffer and
 * produce tearing.
 */

/*
 * Here, we choose a conservative value. A lower value is most likely
 * suitable for GPU use-cases.
 */
#define NR_FLIPS_IN_FLIGHT_THRESHOLD 16

#define CLCD_IRQ_NEXTBASE_UPDATE (1u<<2)

struct pl111_drm_flip_resource;

struct pl111_gem_bo_dma {
	dma_addr_t fb_dev_addr;
	void *fb_cpu_addr;
};

struct pl111_gem_bo_shm {
	struct page **pages;
	dma_addr_t *dma_addrs;
};

struct pl111_gem_bo {
	struct drm_gem_object gem_object;
	u32 type;
	union {
		struct pl111_gem_bo_dma dma;
		struct pl111_gem_bo_shm shm;
	} backing_data;
	struct sg_table *sgt;
};

extern struct pl111_drm_dev_private priv;

struct pl111_drm_framebuffer {
	struct drm_framebuffer fb;
	struct pl111_gem_bo *bo;
};

struct pl111_drm_flip_resource {
#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
	/* This is the kds set associated to the dma_buf we want to flip */
	struct kds_resource_set *kds_res_set;
#endif
	struct drm_framebuffer *fb;
	struct drm_crtc *crtc;
	struct list_head link;
	bool page_flip;
	struct drm_pending_vblank_event *event;
};

struct pl111_drm_crtc {
	struct drm_crtc crtc;
	int crtc_index;

#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
	/* This protects "old_kds_res_set" and "displaying_fb" */
	spinlock_t current_displaying_lock;
	/*
	 * When a buffer is displayed its associated kds resource
	 * will be obtained and stored here. Every time a buffer
	 * flip is completed this old kds set is released and assigned
	 * the kds set of the new buffer.
	 */
	struct kds_resource_set *old_kds_res_set;
	/*
	 * Stores which frame buffer is currently being displayed by
	 * this CRTC or NULL if nothing is being displayed. It is used
	 * to tell whether we need to obtain a set of kds resources for
	 * exported buffer objects.
	 */
	struct drm_framebuffer *displaying_fb;
#endif
	struct drm_display_mode *new_mode;
	struct drm_display_mode *current_mode;
	int last_bpp;

	/*
	 * This spinlock protects "update_queue", "current_update_res"
	 * and calls to do_flip_to_res() which updates the CLCD base
	 * registers.
	 */
	spinlock_t base_update_lock;
	/*
	 * The resource that caused a base address update. Only one can be
	 * pending, hence it's != NULL if there's a pending update
	 */
	struct pl111_drm_flip_resource *current_update_res;
	/* Queue of things waiting to update the base address */
	struct list_head update_queue;

	void (*show_framebuffer_cb)(struct pl111_drm_flip_resource *flip_res,
				struct drm_framebuffer *fb);
};

struct pl111_drm_connector {
	struct drm_connector connector;
};

struct pl111_drm_encoder {
	struct drm_encoder encoder;
};

struct pl111_drm_dev_private {
	struct pl111_drm_crtc *pl111_crtc;

	struct amba_device *amba_dev;
	unsigned long mmio_start;
	__u32 mmio_len;
	void *regs;
	struct clk *clk;
#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
	struct kds_callback kds_cb;
	struct kds_callback kds_obtain_current_cb;
#endif
	/*
	 * Number of flips that were started in show_framebuffer_on_crtc(),
	 * but haven't completed yet - because we do deferred flipping
	 */
	atomic_t nr_flips_in_flight;
	wait_queue_head_t wait_for_flips;

	/*
	 * Used to prevent race between pl111_dma_buf_release and
	 * drm_gem_prime_handle_to_fd
	 */
	struct mutex export_dma_buf_lock;

	uint32_t number_crtcs;

	/* Cache for flip resources used to avoid kmalloc on each page flip */
	struct kmem_cache *page_flip_slab;
};

enum pl111_cursor_size {
	CURSOR_32X32,
	CURSOR_64X64
};

enum pl111_cursor_sync {
	CURSOR_SYNC_NONE,
	CURSOR_SYNC_VSYNC
};


/**
 * Buffer allocation function which is more flexible than dumb_create(),
 * it allows passing driver specific flags to control the kind of buffer
 * to be allocated.
 */
int pl111_drm_gem_create_ioctl(struct drm_device *dev, void *data,
				struct drm_file *file_priv);
 
/****** TODO MIDEGL-1718: this should be moved to uapi/include/drm/pl111_drm.h ********/

/* 
 * Parameters for different buffer objects:
 * bit [0]: backing storage
 *	(0 -> SHM)
 *	(1 -> DMA)
 * bit [2:1]: kind of mapping
 *	(0x0 -> uncached)
 *	(0x1 -> write combine)
 *	(0x2 -> cached)
 */
#define PL111_BOT_MASK		(0x7)
#define PL111_BOT_SHM		(0x0 << 0)
#define PL111_BOT_DMA		(0x1 << 0)
#define PL111_BOT_UNCACHED	(0x0 << 1)
#define PL111_BOT_WC		(0x1 << 1)
#define PL111_BOT_CACHED	(0x2 << 1)

/**
 * User-desired buffer creation information structure.
 *
 * @size: user-desired memory allocation size.
 *      - this size value would be page-aligned internally.
 * @flags: user request for setting memory type or cache attributes as a bit op
 *	- PL111_BOT_DMA / PL111_BOT_SHM
 *	- PL111_BOT_UNCACHED / PL111_BOT_WC / PL111_BOT_CACHED
 * @handle: returned a handle to created gem object.
 *      - this handle will be set by gem module of kernel side.
 */
struct drm_pl111_gem_create {
	uint32_t height;
	uint32_t width;
	uint32_t bpp;
	uint32_t flags;
	/* handle, pitch, size will be returned */
	uint32_t handle;
	uint32_t pitch;
	uint64_t size;
};

#define DRM_PL111_GEM_CREATE		0x00

#define DRM_IOCTL_PL111_GEM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + \
			DRM_PL111_GEM_CREATE, struct drm_pl111_gem_create)
/****************************************************************************/

#define PL111_FB_FROM_FRAMEBUFFER(drm_fb) \
	(container_of(drm_fb, struct pl111_drm_framebuffer, fb))

#define PL111_BO_FROM_FRAMEBUFFER(drm_fb) \
	(container_of(drm_fb, struct pl111_drm_framebuffer, fb)->bo)

#define PL111_BO_FROM_GEM(gem_obj) \
	container_of(gem_obj, struct pl111_gem_bo, gem_object)

#define to_pl111_crtc(x) container_of(x, struct pl111_drm_crtc, crtc)

#define PL111_ENCODER_FROM_ENCODER(x) \
	container_of(x, struct pl111_drm_encoder, encoder)

#define PL111_CONNECTOR_FROM_CONNECTOR(x) \
	container_of(x, struct pl111_drm_connector, connector)

#include "pl111_drm_funcs.h"

#endif /* _PL111_DRM_H_ */