xref: /aosp_15_r20/external/igt-gpu-tools/tools/skl_ddb_allocation.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2014 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*d83cc019SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  */
23*d83cc019SAndroid Build Coastguard Worker 
24*d83cc019SAndroid Build Coastguard Worker #include <stdint.h>
25*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
26*d83cc019SAndroid Build Coastguard Worker #include <stdbool.h>
27*d83cc019SAndroid Build Coastguard Worker #include <stddef.h>
28*d83cc019SAndroid Build Coastguard Worker #include <string.h>
29*d83cc019SAndroid Build Coastguard Worker 
30*d83cc019SAndroid Build Coastguard Worker /**
31*d83cc019SAndroid Build Coastguard Worker  * container_of - cast a member of a structure out to the containing structure
32*d83cc019SAndroid Build Coastguard Worker  * @ptr:	the pointer to the member.
33*d83cc019SAndroid Build Coastguard Worker  * @type:	the type of the container struct this is embedded in.
34*d83cc019SAndroid Build Coastguard Worker  * @member:	the name of the member within the struct.
35*d83cc019SAndroid Build Coastguard Worker  *
36*d83cc019SAndroid Build Coastguard Worker  */
37*d83cc019SAndroid Build Coastguard Worker #define container_of(ptr, type, member) ({			\
38*d83cc019SAndroid Build Coastguard Worker 	typeof( ((type *)0)->member ) *__mptr = (ptr);	\
39*d83cc019SAndroid Build Coastguard Worker 	(type *)( (char *)__mptr - offsetof(type,member) );})
40*d83cc019SAndroid Build Coastguard Worker 
41*d83cc019SAndroid Build Coastguard Worker #define div_u64(a, b)	((a) / (b))
42*d83cc019SAndroid Build Coastguard Worker 
43*d83cc019SAndroid Build Coastguard Worker /*
44*d83cc019SAndroid Build Coastguard Worker  * Stub a few defines/structures
45*d83cc019SAndroid Build Coastguard Worker  */
46*d83cc019SAndroid Build Coastguard Worker 
47*d83cc019SAndroid Build Coastguard Worker #define I915_MAX_PIPES	3
48*d83cc019SAndroid Build Coastguard Worker #define I915_MAX_PLANES	3
49*d83cc019SAndroid Build Coastguard Worker #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
50*d83cc019SAndroid Build Coastguard Worker 
51*d83cc019SAndroid Build Coastguard Worker #define for_each_pipe(p) for ((p) = 0; (p) < 3; (p)++)
52*d83cc019SAndroid Build Coastguard Worker #define for_each_plane(pipe, p) for ((p) = 0; (p) < 3; (p)++)
53*d83cc019SAndroid Build Coastguard Worker 
54*d83cc019SAndroid Build Coastguard Worker #define for_each_crtc(dev, crtc) \
55*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < 3 && (crtc = &crtcs[i].base); i++)
56*d83cc019SAndroid Build Coastguard Worker 
57*d83cc019SAndroid Build Coastguard Worker #define for_each_intel_crtc(dev, intel_crtc) \
58*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < 3, intel_crtc = &crtcs[i]; i++)
59*d83cc019SAndroid Build Coastguard Worker 
60*d83cc019SAndroid Build Coastguard Worker enum pipe {
61*d83cc019SAndroid Build Coastguard Worker 	PIPE_A,
62*d83cc019SAndroid Build Coastguard Worker 	PIPE_B,
63*d83cc019SAndroid Build Coastguard Worker 	PIPE_C,
64*d83cc019SAndroid Build Coastguard Worker };
65*d83cc019SAndroid Build Coastguard Worker 
66*d83cc019SAndroid Build Coastguard Worker enum plane {
67*d83cc019SAndroid Build Coastguard Worker 	PLANE_1,
68*d83cc019SAndroid Build Coastguard Worker 	PLANE_2,
69*d83cc019SAndroid Build Coastguard Worker 	PLANE_3,
70*d83cc019SAndroid Build Coastguard Worker };
71*d83cc019SAndroid Build Coastguard Worker 
72*d83cc019SAndroid Build Coastguard Worker #define pipe_name(p) ((p) + 'A')
73*d83cc019SAndroid Build Coastguard Worker 
74*d83cc019SAndroid Build Coastguard Worker struct drm_device {
75*d83cc019SAndroid Build Coastguard Worker 	void *dev_private;
76*d83cc019SAndroid Build Coastguard Worker };
77*d83cc019SAndroid Build Coastguard Worker 
78*d83cc019SAndroid Build Coastguard Worker struct drm_i915_private {
79*d83cc019SAndroid Build Coastguard Worker 	struct drm_device *dev;
80*d83cc019SAndroid Build Coastguard Worker };
81*d83cc019SAndroid Build Coastguard Worker 
82*d83cc019SAndroid Build Coastguard Worker struct drm_crtc {
83*d83cc019SAndroid Build Coastguard Worker 	struct drm_device *dev;
84*d83cc019SAndroid Build Coastguard Worker 	bool active;
85*d83cc019SAndroid Build Coastguard Worker };
86*d83cc019SAndroid Build Coastguard Worker 
intel_crtc_active(struct drm_crtc * crtc)87*d83cc019SAndroid Build Coastguard Worker static bool intel_crtc_active(struct drm_crtc *crtc)
88*d83cc019SAndroid Build Coastguard Worker {
89*d83cc019SAndroid Build Coastguard Worker 	return crtc->active;
90*d83cc019SAndroid Build Coastguard Worker }
91*d83cc019SAndroid Build Coastguard Worker 
92*d83cc019SAndroid Build Coastguard Worker struct intel_crtc {
93*d83cc019SAndroid Build Coastguard Worker 	struct drm_crtc base;
94*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe;
95*d83cc019SAndroid Build Coastguard Worker };
96*d83cc019SAndroid Build Coastguard Worker 
intel_num_planes(struct intel_crtc * crtc)97*d83cc019SAndroid Build Coastguard Worker static int intel_num_planes(struct intel_crtc *crtc)
98*d83cc019SAndroid Build Coastguard Worker {
99*d83cc019SAndroid Build Coastguard Worker 	return 3;
100*d83cc019SAndroid Build Coastguard Worker }
101*d83cc019SAndroid Build Coastguard Worker 
102*d83cc019SAndroid Build Coastguard Worker struct intel_crtc crtcs[I915_MAX_PIPES];
103*d83cc019SAndroid Build Coastguard Worker 
104*d83cc019SAndroid Build Coastguard Worker #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
105*d83cc019SAndroid Build Coastguard Worker 
106*d83cc019SAndroid Build Coastguard Worker /*
107*d83cc019SAndroid Build Coastguard Worker  * DDB code
108*d83cc019SAndroid Build Coastguard Worker  */
109*d83cc019SAndroid Build Coastguard Worker 
110*d83cc019SAndroid Build Coastguard Worker struct intel_wm_config {
111*d83cc019SAndroid Build Coastguard Worker 	unsigned int num_pipes_active;
112*d83cc019SAndroid Build Coastguard Worker };
113*d83cc019SAndroid Build Coastguard Worker 
114*d83cc019SAndroid Build Coastguard Worker struct intel_plane_wm_parameters {
115*d83cc019SAndroid Build Coastguard Worker 	uint32_t horiz_pixels;
116*d83cc019SAndroid Build Coastguard Worker 	uint32_t vert_pixels;
117*d83cc019SAndroid Build Coastguard Worker 	uint8_t bytes_per_pixel;
118*d83cc019SAndroid Build Coastguard Worker 	bool enabled;
119*d83cc019SAndroid Build Coastguard Worker 	bool scaled;
120*d83cc019SAndroid Build Coastguard Worker };
121*d83cc019SAndroid Build Coastguard Worker 
122*d83cc019SAndroid Build Coastguard Worker struct skl_pipe_wm_parameters {
123*d83cc019SAndroid Build Coastguard Worker 	bool active;
124*d83cc019SAndroid Build Coastguard Worker 	uint32_t pipe_htotal;
125*d83cc019SAndroid Build Coastguard Worker 	uint32_t pixel_rate; /* in KHz */
126*d83cc019SAndroid Build Coastguard Worker 	struct intel_plane_wm_parameters plane[I915_MAX_PLANES];
127*d83cc019SAndroid Build Coastguard Worker 	struct intel_plane_wm_parameters cursor;
128*d83cc019SAndroid Build Coastguard Worker };
129*d83cc019SAndroid Build Coastguard Worker 
130*d83cc019SAndroid Build Coastguard Worker struct skl_ddb_entry {
131*d83cc019SAndroid Build Coastguard Worker 	uint16_t start, end;	/* in number of blocks. 'end' is exclusive */
132*d83cc019SAndroid Build Coastguard Worker };
133*d83cc019SAndroid Build Coastguard Worker 
skl_ddb_entry_size(const struct skl_ddb_entry * entry)134*d83cc019SAndroid Build Coastguard Worker static inline uint16_t skl_ddb_entry_size(const struct skl_ddb_entry *entry)
135*d83cc019SAndroid Build Coastguard Worker {
136*d83cc019SAndroid Build Coastguard Worker 	/* end not set, clearly no allocation here. start can be 0 though */
137*d83cc019SAndroid Build Coastguard Worker 	if (entry->end == 0)
138*d83cc019SAndroid Build Coastguard Worker 		return 0;
139*d83cc019SAndroid Build Coastguard Worker 
140*d83cc019SAndroid Build Coastguard Worker 	return entry->end - entry->start;
141*d83cc019SAndroid Build Coastguard Worker }
142*d83cc019SAndroid Build Coastguard Worker 
skl_ddb_entry_equal(const struct skl_ddb_entry * e1,const struct skl_ddb_entry * e2)143*d83cc019SAndroid Build Coastguard Worker static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
144*d83cc019SAndroid Build Coastguard Worker 				       const struct skl_ddb_entry *e2)
145*d83cc019SAndroid Build Coastguard Worker {
146*d83cc019SAndroid Build Coastguard Worker 	if (e1->start == e2->start && e1->end == e2->end)
147*d83cc019SAndroid Build Coastguard Worker 		return true;
148*d83cc019SAndroid Build Coastguard Worker 
149*d83cc019SAndroid Build Coastguard Worker 	return false;
150*d83cc019SAndroid Build Coastguard Worker }
151*d83cc019SAndroid Build Coastguard Worker 
152*d83cc019SAndroid Build Coastguard Worker struct skl_ddb_allocation {
153*d83cc019SAndroid Build Coastguard Worker 	struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES];
154*d83cc019SAndroid Build Coastguard Worker 	struct skl_ddb_entry cursor[I915_MAX_PIPES];
155*d83cc019SAndroid Build Coastguard Worker };
156*d83cc019SAndroid Build Coastguard Worker 
157*d83cc019SAndroid Build Coastguard Worker /*
158*d83cc019SAndroid Build Coastguard Worker  * On gen9, we need to allocate Display Data Buffer (DDB) portions to the
159*d83cc019SAndroid Build Coastguard Worker  * different active planes.
160*d83cc019SAndroid Build Coastguard Worker  */
161*d83cc019SAndroid Build Coastguard Worker 
162*d83cc019SAndroid Build Coastguard Worker #define SKL_DDB_SIZE		896	/* in blocks */
163*d83cc019SAndroid Build Coastguard Worker 
164*d83cc019SAndroid Build Coastguard Worker static void
skl_ddb_get_pipe_allocation_limits(struct drm_device * dev,struct drm_crtc * for_crtc,const struct intel_wm_config * config,const struct skl_pipe_wm_parameters * params,struct skl_ddb_entry * alloc)165*d83cc019SAndroid Build Coastguard Worker skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
166*d83cc019SAndroid Build Coastguard Worker 				   struct drm_crtc *for_crtc,
167*d83cc019SAndroid Build Coastguard Worker 				   const struct intel_wm_config *config,
168*d83cc019SAndroid Build Coastguard Worker 				   const struct skl_pipe_wm_parameters *params,
169*d83cc019SAndroid Build Coastguard Worker 				   struct skl_ddb_entry *alloc /* out */)
170*d83cc019SAndroid Build Coastguard Worker {
171*d83cc019SAndroid Build Coastguard Worker 	struct drm_crtc *crtc;
172*d83cc019SAndroid Build Coastguard Worker 	unsigned int pipe_size, ddb_size;
173*d83cc019SAndroid Build Coastguard Worker 	int nth_active_pipe;
174*d83cc019SAndroid Build Coastguard Worker 
175*d83cc019SAndroid Build Coastguard Worker 	if (!params->active) {
176*d83cc019SAndroid Build Coastguard Worker 		alloc->start = 0;
177*d83cc019SAndroid Build Coastguard Worker 		alloc->end = 0;
178*d83cc019SAndroid Build Coastguard Worker 		return;
179*d83cc019SAndroid Build Coastguard Worker 	}
180*d83cc019SAndroid Build Coastguard Worker 
181*d83cc019SAndroid Build Coastguard Worker 	ddb_size = SKL_DDB_SIZE;
182*d83cc019SAndroid Build Coastguard Worker 	ddb_size -= 4; /* 4 blocks for bypass path allocation */
183*d83cc019SAndroid Build Coastguard Worker 
184*d83cc019SAndroid Build Coastguard Worker 	nth_active_pipe = 0;
185*d83cc019SAndroid Build Coastguard Worker 	for_each_crtc(dev, crtc) {
186*d83cc019SAndroid Build Coastguard Worker 		if (!intel_crtc_active(crtc))
187*d83cc019SAndroid Build Coastguard Worker 			continue;
188*d83cc019SAndroid Build Coastguard Worker 
189*d83cc019SAndroid Build Coastguard Worker 		if (crtc == for_crtc)
190*d83cc019SAndroid Build Coastguard Worker 			break;
191*d83cc019SAndroid Build Coastguard Worker 
192*d83cc019SAndroid Build Coastguard Worker 		nth_active_pipe++;
193*d83cc019SAndroid Build Coastguard Worker 	}
194*d83cc019SAndroid Build Coastguard Worker 
195*d83cc019SAndroid Build Coastguard Worker 	pipe_size = ddb_size / config->num_pipes_active;
196*d83cc019SAndroid Build Coastguard Worker 	alloc->start = nth_active_pipe * ddb_size / config->num_pipes_active;
197*d83cc019SAndroid Build Coastguard Worker 	alloc->end = alloc->start + pipe_size;
198*d83cc019SAndroid Build Coastguard Worker }
199*d83cc019SAndroid Build Coastguard Worker 
skl_cursor_allocation(const struct intel_wm_config * config)200*d83cc019SAndroid Build Coastguard Worker static unsigned int skl_cursor_allocation(const struct intel_wm_config *config)
201*d83cc019SAndroid Build Coastguard Worker {
202*d83cc019SAndroid Build Coastguard Worker 	if (config->num_pipes_active == 1)
203*d83cc019SAndroid Build Coastguard Worker 		return 32;
204*d83cc019SAndroid Build Coastguard Worker 
205*d83cc019SAndroid Build Coastguard Worker 	return 8;
206*d83cc019SAndroid Build Coastguard Worker }
207*d83cc019SAndroid Build Coastguard Worker 
208*d83cc019SAndroid Build Coastguard Worker static unsigned int
skl_plane_relative_data_rate(const struct intel_plane_wm_parameters * p)209*d83cc019SAndroid Build Coastguard Worker skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p)
210*d83cc019SAndroid Build Coastguard Worker {
211*d83cc019SAndroid Build Coastguard Worker 	return p->horiz_pixels * p->vert_pixels * p->bytes_per_pixel;
212*d83cc019SAndroid Build Coastguard Worker }
213*d83cc019SAndroid Build Coastguard Worker 
214*d83cc019SAndroid Build Coastguard Worker /*
215*d83cc019SAndroid Build Coastguard Worker  * We don't overflow 32 bits. Worst case is 3 planes enabled, each fetching
216*d83cc019SAndroid Build Coastguard Worker  * a 8192x4096@32bpp framebuffer:
217*d83cc019SAndroid Build Coastguard Worker  *   3 * 4096 * 8192  * 4 < 2^32
218*d83cc019SAndroid Build Coastguard Worker  */
219*d83cc019SAndroid Build Coastguard Worker static unsigned int
skl_get_total_relative_data_rate(struct intel_crtc * intel_crtc,const struct skl_pipe_wm_parameters * params)220*d83cc019SAndroid Build Coastguard Worker skl_get_total_relative_data_rate(struct intel_crtc *intel_crtc,
221*d83cc019SAndroid Build Coastguard Worker 				 const struct skl_pipe_wm_parameters *params)
222*d83cc019SAndroid Build Coastguard Worker {
223*d83cc019SAndroid Build Coastguard Worker 	unsigned int total_data_rate = 0;
224*d83cc019SAndroid Build Coastguard Worker 	int plane;
225*d83cc019SAndroid Build Coastguard Worker 
226*d83cc019SAndroid Build Coastguard Worker 	for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
227*d83cc019SAndroid Build Coastguard Worker 		const struct intel_plane_wm_parameters *p;
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker 		p = &params->plane[plane];
230*d83cc019SAndroid Build Coastguard Worker 		if (!p->enabled)
231*d83cc019SAndroid Build Coastguard Worker 			continue;
232*d83cc019SAndroid Build Coastguard Worker 
233*d83cc019SAndroid Build Coastguard Worker 		total_data_rate += skl_plane_relative_data_rate(p);
234*d83cc019SAndroid Build Coastguard Worker 	}
235*d83cc019SAndroid Build Coastguard Worker 
236*d83cc019SAndroid Build Coastguard Worker 	return total_data_rate;
237*d83cc019SAndroid Build Coastguard Worker }
238*d83cc019SAndroid Build Coastguard Worker 
239*d83cc019SAndroid Build Coastguard Worker static void
skl_allocate_pipe_ddb(struct drm_crtc * crtc,const struct intel_wm_config * config,const struct skl_pipe_wm_parameters * params,struct skl_ddb_allocation * ddb)240*d83cc019SAndroid Build Coastguard Worker skl_allocate_pipe_ddb(struct drm_crtc *crtc,
241*d83cc019SAndroid Build Coastguard Worker 		      const struct intel_wm_config *config,
242*d83cc019SAndroid Build Coastguard Worker 		      const struct skl_pipe_wm_parameters *params,
243*d83cc019SAndroid Build Coastguard Worker 		      struct skl_ddb_allocation *ddb /* out */)
244*d83cc019SAndroid Build Coastguard Worker {
245*d83cc019SAndroid Build Coastguard Worker 	struct drm_device *dev = crtc->dev;
246*d83cc019SAndroid Build Coastguard Worker 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
247*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = intel_crtc->pipe;
248*d83cc019SAndroid Build Coastguard Worker 	struct skl_ddb_entry alloc;
249*d83cc019SAndroid Build Coastguard Worker 	uint16_t alloc_size, start, cursor_blocks;
250*d83cc019SAndroid Build Coastguard Worker 	uint16_t minimum[I915_MAX_PLANES];
251*d83cc019SAndroid Build Coastguard Worker 	unsigned int total_data_rate;
252*d83cc019SAndroid Build Coastguard Worker 	int plane;
253*d83cc019SAndroid Build Coastguard Worker 
254*d83cc019SAndroid Build Coastguard Worker 	skl_ddb_get_pipe_allocation_limits(dev, crtc, config, params, &alloc);
255*d83cc019SAndroid Build Coastguard Worker 	alloc_size = skl_ddb_entry_size(&alloc);
256*d83cc019SAndroid Build Coastguard Worker 	if (alloc_size == 0) {
257*d83cc019SAndroid Build Coastguard Worker 		memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
258*d83cc019SAndroid Build Coastguard Worker 		memset(&ddb->cursor[pipe], 0, sizeof(ddb->cursor[pipe]));
259*d83cc019SAndroid Build Coastguard Worker 		return;
260*d83cc019SAndroid Build Coastguard Worker 	}
261*d83cc019SAndroid Build Coastguard Worker 
262*d83cc019SAndroid Build Coastguard Worker 	cursor_blocks = skl_cursor_allocation(config);
263*d83cc019SAndroid Build Coastguard Worker 	ddb->cursor[pipe].start = alloc.end - cursor_blocks;
264*d83cc019SAndroid Build Coastguard Worker 	ddb->cursor[pipe].end = alloc.end;
265*d83cc019SAndroid Build Coastguard Worker 
266*d83cc019SAndroid Build Coastguard Worker 	alloc_size -= cursor_blocks;
267*d83cc019SAndroid Build Coastguard Worker 	alloc.end -= cursor_blocks;
268*d83cc019SAndroid Build Coastguard Worker 
269*d83cc019SAndroid Build Coastguard Worker 	/* 1. Allocate the mininum required blocks for each active plane */
270*d83cc019SAndroid Build Coastguard Worker 	for_each_plane(pipe, plane) {
271*d83cc019SAndroid Build Coastguard Worker 		const struct intel_plane_wm_parameters *p;
272*d83cc019SAndroid Build Coastguard Worker 
273*d83cc019SAndroid Build Coastguard Worker 		p = &params->plane[plane];
274*d83cc019SAndroid Build Coastguard Worker 		if (!p->enabled)
275*d83cc019SAndroid Build Coastguard Worker 			continue;
276*d83cc019SAndroid Build Coastguard Worker 
277*d83cc019SAndroid Build Coastguard Worker 		minimum[plane] = 8;
278*d83cc019SAndroid Build Coastguard Worker 		alloc_size -= minimum[plane];
279*d83cc019SAndroid Build Coastguard Worker 	}
280*d83cc019SAndroid Build Coastguard Worker 
281*d83cc019SAndroid Build Coastguard Worker 	/*
282*d83cc019SAndroid Build Coastguard Worker 	 * 2. Distribute the remaining space in proportion to the amount of
283*d83cc019SAndroid Build Coastguard Worker 	 * data each plane needs to fetch from memory.
284*d83cc019SAndroid Build Coastguard Worker 	 *
285*d83cc019SAndroid Build Coastguard Worker 	 * FIXME: we may not allocate every single block here.
286*d83cc019SAndroid Build Coastguard Worker 	 */
287*d83cc019SAndroid Build Coastguard Worker 	total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params);
288*d83cc019SAndroid Build Coastguard Worker 
289*d83cc019SAndroid Build Coastguard Worker 	start = alloc.start;
290*d83cc019SAndroid Build Coastguard Worker 	for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
291*d83cc019SAndroid Build Coastguard Worker 		const struct intel_plane_wm_parameters *p;
292*d83cc019SAndroid Build Coastguard Worker 		unsigned int data_rate;
293*d83cc019SAndroid Build Coastguard Worker 		uint16_t plane_blocks;
294*d83cc019SAndroid Build Coastguard Worker 
295*d83cc019SAndroid Build Coastguard Worker 		p = &params->plane[plane];
296*d83cc019SAndroid Build Coastguard Worker 		if (!p->enabled)
297*d83cc019SAndroid Build Coastguard Worker 			continue;
298*d83cc019SAndroid Build Coastguard Worker 
299*d83cc019SAndroid Build Coastguard Worker 		data_rate = skl_plane_relative_data_rate(p);
300*d83cc019SAndroid Build Coastguard Worker 
301*d83cc019SAndroid Build Coastguard Worker 		/*
302*d83cc019SAndroid Build Coastguard Worker 		 * promote the expression to 64 bits to avoid overflowing, the
303*d83cc019SAndroid Build Coastguard Worker 		 * result is < available as data_rate / total_data_rate < 1
304*d83cc019SAndroid Build Coastguard Worker 		 */
305*d83cc019SAndroid Build Coastguard Worker 		plane_blocks = minimum[plane];
306*d83cc019SAndroid Build Coastguard Worker 		plane_blocks += div_u64((uint64_t)alloc_size * data_rate,
307*d83cc019SAndroid Build Coastguard Worker 					total_data_rate);
308*d83cc019SAndroid Build Coastguard Worker 
309*d83cc019SAndroid Build Coastguard Worker 		ddb->plane[pipe][plane].start = start;
310*d83cc019SAndroid Build Coastguard Worker 		ddb->plane[pipe][plane].end = start + plane_blocks;
311*d83cc019SAndroid Build Coastguard Worker 
312*d83cc019SAndroid Build Coastguard Worker 		start += plane_blocks;
313*d83cc019SAndroid Build Coastguard Worker 	}
314*d83cc019SAndroid Build Coastguard Worker 
315*d83cc019SAndroid Build Coastguard Worker }
316*d83cc019SAndroid Build Coastguard Worker 
skl_ddb_check_entry(struct skl_ddb_entry * entry,int16_t * cursor)317*d83cc019SAndroid Build Coastguard Worker static void skl_ddb_check_entry(struct skl_ddb_entry *entry, int16_t *cursor)
318*d83cc019SAndroid Build Coastguard Worker {
319*d83cc019SAndroid Build Coastguard Worker 
320*d83cc019SAndroid Build Coastguard Worker 	if (skl_ddb_entry_size(entry) == 0)
321*d83cc019SAndroid Build Coastguard Worker 		return;
322*d83cc019SAndroid Build Coastguard Worker 
323*d83cc019SAndroid Build Coastguard Worker 	/* check that ->start is the next available block */
324*d83cc019SAndroid Build Coastguard Worker 	if (entry->start < *cursor)
325*d83cc019SAndroid Build Coastguard Worker 		printf("error: allocation overlaps previous block\n");
326*d83cc019SAndroid Build Coastguard Worker 	else if (entry->start >= *cursor + 1)
327*d83cc019SAndroid Build Coastguard Worker 		printf("warning: allocation leaves a hole\n");
328*d83cc019SAndroid Build Coastguard Worker 
329*d83cc019SAndroid Build Coastguard Worker 	*cursor = entry->end;
330*d83cc019SAndroid Build Coastguard Worker }
331*d83cc019SAndroid Build Coastguard Worker 
skl_ddb_check_last_allocation(int16_t cursor)332*d83cc019SAndroid Build Coastguard Worker static void skl_ddb_check_last_allocation(int16_t cursor)
333*d83cc019SAndroid Build Coastguard Worker {
334*d83cc019SAndroid Build Coastguard Worker 	uint16_t last_offset = SKL_DDB_SIZE - 4;
335*d83cc019SAndroid Build Coastguard Worker 
336*d83cc019SAndroid Build Coastguard Worker 	if (cursor < last_offset)
337*d83cc019SAndroid Build Coastguard Worker 		printf("warning: %d blocks not allocated\n",
338*d83cc019SAndroid Build Coastguard Worker 		       last_offset - cursor);
339*d83cc019SAndroid Build Coastguard Worker 	else if (cursor > last_offset)
340*d83cc019SAndroid Build Coastguard Worker 		printf("error: allocation greater than available space\n");
341*d83cc019SAndroid Build Coastguard Worker }
342*d83cc019SAndroid Build Coastguard Worker 
skl_ddb_print(struct skl_ddb_allocation * ddb)343*d83cc019SAndroid Build Coastguard Worker static void skl_ddb_print(struct skl_ddb_allocation *ddb)
344*d83cc019SAndroid Build Coastguard Worker {
345*d83cc019SAndroid Build Coastguard Worker 	struct skl_ddb_entry *entry;
346*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe;
347*d83cc019SAndroid Build Coastguard Worker 	int plane;
348*d83cc019SAndroid Build Coastguard Worker 	int16_t cursor = 0;
349*d83cc019SAndroid Build Coastguard Worker 
350*d83cc019SAndroid Build Coastguard Worker 	printf("%-15s%8s%8s%8s\n", "", "Start", "End", "Size");
351*d83cc019SAndroid Build Coastguard Worker 
352*d83cc019SAndroid Build Coastguard Worker 	for_each_pipe(pipe) {
353*d83cc019SAndroid Build Coastguard Worker 		printf("Pipe %c\n", pipe_name(pipe));
354*d83cc019SAndroid Build Coastguard Worker 
355*d83cc019SAndroid Build Coastguard Worker 		for_each_plane(pipe, plane) {
356*d83cc019SAndroid Build Coastguard Worker 			entry = &ddb->plane[pipe][plane];
357*d83cc019SAndroid Build Coastguard Worker 
358*d83cc019SAndroid Build Coastguard Worker 			printf("  Plane%-8d%8u%8u%8u\n", plane + 1,
359*d83cc019SAndroid Build Coastguard Worker 			       entry->start, entry->end,
360*d83cc019SAndroid Build Coastguard Worker 			       skl_ddb_entry_size(entry));
361*d83cc019SAndroid Build Coastguard Worker 
362*d83cc019SAndroid Build Coastguard Worker 			skl_ddb_check_entry(entry, &cursor);
363*d83cc019SAndroid Build Coastguard Worker 		}
364*d83cc019SAndroid Build Coastguard Worker 
365*d83cc019SAndroid Build Coastguard Worker 		entry = &ddb->cursor[pipe];
366*d83cc019SAndroid Build Coastguard Worker 		printf("  %-13s%8u%8u%8u\n", "Cursor", entry->start,
367*d83cc019SAndroid Build Coastguard Worker 		       entry->end, skl_ddb_entry_size(entry));
368*d83cc019SAndroid Build Coastguard Worker 
369*d83cc019SAndroid Build Coastguard Worker 		skl_ddb_check_entry(entry, &cursor);
370*d83cc019SAndroid Build Coastguard Worker 	}
371*d83cc019SAndroid Build Coastguard Worker 
372*d83cc019SAndroid Build Coastguard Worker 	skl_ddb_check_last_allocation(cursor);
373*d83cc019SAndroid Build Coastguard Worker }
374*d83cc019SAndroid Build Coastguard Worker 
375*d83cc019SAndroid Build Coastguard Worker static struct drm_device drm_device;
376*d83cc019SAndroid Build Coastguard Worker static struct drm_i915_private drm_i915_private;
377*d83cc019SAndroid Build Coastguard Worker 
init_stub(void)378*d83cc019SAndroid Build Coastguard Worker static void init_stub(void)
379*d83cc019SAndroid Build Coastguard Worker {
380*d83cc019SAndroid Build Coastguard Worker 	int i;
381*d83cc019SAndroid Build Coastguard Worker 
382*d83cc019SAndroid Build Coastguard Worker 	drm_device.dev_private = &drm_i915_private;
383*d83cc019SAndroid Build Coastguard Worker 	drm_i915_private.dev = &drm_device;
384*d83cc019SAndroid Build Coastguard Worker 
385*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < I915_MAX_PIPES; i++) {
386*d83cc019SAndroid Build Coastguard Worker 		crtcs[i].base.dev = &drm_device;
387*d83cc019SAndroid Build Coastguard Worker 		crtcs[i].pipe = i;
388*d83cc019SAndroid Build Coastguard Worker 	}
389*d83cc019SAndroid Build Coastguard Worker }
390*d83cc019SAndroid Build Coastguard Worker 
391*d83cc019SAndroid Build Coastguard Worker struct wm_input {
392*d83cc019SAndroid Build Coastguard Worker 	struct intel_wm_config config;
393*d83cc019SAndroid Build Coastguard Worker 	struct skl_pipe_wm_parameters params[I915_MAX_PIPES];
394*d83cc019SAndroid Build Coastguard Worker };
395*d83cc019SAndroid Build Coastguard Worker 
wm_input_reset(struct wm_input * in)396*d83cc019SAndroid Build Coastguard Worker static void wm_input_reset(struct wm_input *in)
397*d83cc019SAndroid Build Coastguard Worker {
398*d83cc019SAndroid Build Coastguard Worker 	memset(in, 0, sizeof(*in));
399*d83cc019SAndroid Build Coastguard Worker }
400*d83cc019SAndroid Build Coastguard Worker 
wm_enable_plane(struct wm_input * in,enum pipe pipe,enum plane plane,uint32_t width,uint32_t height,int bpp)401*d83cc019SAndroid Build Coastguard Worker static void wm_enable_plane(struct wm_input *in,
402*d83cc019SAndroid Build Coastguard Worker 			    enum pipe pipe, enum plane plane,
403*d83cc019SAndroid Build Coastguard Worker 			    uint32_t width, uint32_t height, int bpp)
404*d83cc019SAndroid Build Coastguard Worker {
405*d83cc019SAndroid Build Coastguard Worker 	enum pipe i;
406*d83cc019SAndroid Build Coastguard Worker 
407*d83cc019SAndroid Build Coastguard Worker 	in->params[pipe].active = 1;
408*d83cc019SAndroid Build Coastguard Worker 
409*d83cc019SAndroid Build Coastguard Worker 	in->config.num_pipes_active = 0;
410*d83cc019SAndroid Build Coastguard Worker 	for_each_pipe(i)
411*d83cc019SAndroid Build Coastguard Worker 		if (in->params[i].active)
412*d83cc019SAndroid Build Coastguard Worker 			in->config.num_pipes_active++;
413*d83cc019SAndroid Build Coastguard Worker 
414*d83cc019SAndroid Build Coastguard Worker 	in->params[pipe].plane[plane].horiz_pixels = width;
415*d83cc019SAndroid Build Coastguard Worker 	in->params[pipe].plane[plane].vert_pixels = height;
416*d83cc019SAndroid Build Coastguard Worker 	in->params[pipe].plane[plane].bytes_per_pixel = bpp;
417*d83cc019SAndroid Build Coastguard Worker 	in->params[pipe].plane[plane].enabled = true;
418*d83cc019SAndroid Build Coastguard Worker }
419*d83cc019SAndroid Build Coastguard Worker 
skl_ddb_allocate(struct wm_input * in,struct skl_ddb_allocation * out)420*d83cc019SAndroid Build Coastguard Worker static void skl_ddb_allocate(struct wm_input *in,
421*d83cc019SAndroid Build Coastguard Worker 			     struct skl_ddb_allocation *out)
422*d83cc019SAndroid Build Coastguard Worker {
423*d83cc019SAndroid Build Coastguard Worker 	struct drm_crtc *crtc;
424*d83cc019SAndroid Build Coastguard Worker 
425*d83cc019SAndroid Build Coastguard Worker 	for_each_crtc(, crtc) {
426*d83cc019SAndroid Build Coastguard Worker 		enum pipe pipe = to_intel_crtc(crtc)->pipe;
427*d83cc019SAndroid Build Coastguard Worker 
428*d83cc019SAndroid Build Coastguard Worker 		skl_allocate_pipe_ddb(crtc,
429*d83cc019SAndroid Build Coastguard Worker 				      &in->config, &in->params[pipe], out);
430*d83cc019SAndroid Build Coastguard Worker 	}
431*d83cc019SAndroid Build Coastguard Worker }
432*d83cc019SAndroid Build Coastguard Worker 
main(int argc,char ** argv)433*d83cc019SAndroid Build Coastguard Worker int main(int argc, char **argv)
434*d83cc019SAndroid Build Coastguard Worker {
435*d83cc019SAndroid Build Coastguard Worker 	struct wm_input in;
436*d83cc019SAndroid Build Coastguard Worker 	static struct skl_ddb_allocation ddb;
437*d83cc019SAndroid Build Coastguard Worker 
438*d83cc019SAndroid Build Coastguard Worker 	init_stub();
439*d83cc019SAndroid Build Coastguard Worker 
440*d83cc019SAndroid Build Coastguard Worker 	wm_input_reset(&in);
441*d83cc019SAndroid Build Coastguard Worker 	wm_enable_plane(&in, PIPE_A, PLANE_1, 1280, 1024, 4);
442*d83cc019SAndroid Build Coastguard Worker 	wm_enable_plane(&in, PIPE_A, PLANE_2,  100,  100, 4);
443*d83cc019SAndroid Build Coastguard Worker 	skl_ddb_allocate(&in, &ddb);
444*d83cc019SAndroid Build Coastguard Worker 	skl_ddb_print(&ddb);
445*d83cc019SAndroid Build Coastguard Worker 
446*d83cc019SAndroid Build Coastguard Worker 	return 0;
447*d83cc019SAndroid Build Coastguard Worker }
448