1 /*
2  * Copyright © 2014 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /**
25  * DOC: atomic plane helpers
26  *
27  * The functions here are used by the atomic plane helper functions to
28  * implement legacy plane updates (i.e., drm_plane->update_plane() and
29  * drm_plane->disable_plane()).  This allows plane updates to use the
30  * atomic state infrastructure and perform plane updates as separate
31  * prepare/check/commit/cleanup steps.
32  */
33 
34 #include <drm/drm_atomic_helper.h>
35 #include <drm/drm_fourcc.h>
36 #include <drm/drm_plane_helper.h>
37 
38 #include "i915_trace.h"
39 #include "intel_atomic_plane.h"
40 #include "intel_display_types.h"
41 #include "intel_pm.h"
42 #include "intel_sprite.h"
43 
44 struct intel_plane *intel_plane_alloc(void)
45 {
46 	struct intel_plane_state *plane_state;
47 	struct intel_plane *plane;
48 
49 	plane = kzalloc(sizeof(*plane), GFP_KERNEL);
50 	if (!plane)
51 		return ERR_PTR(-ENOMEM);
52 
53 	plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
54 	if (!plane_state) {
55 		kfree(plane);
56 		return ERR_PTR(-ENOMEM);
57 	}
58 
59 	__drm_atomic_helper_plane_reset(&plane->base, &plane_state->base);
60 	plane_state->scaler_id = -1;
61 
62 	return plane;
63 }
64 
65 void intel_plane_free(struct intel_plane *plane)
66 {
67 	intel_plane_destroy_state(&plane->base, plane->base.state);
68 	kfree(plane);
69 }
70 
71 /**
72  * intel_plane_duplicate_state - duplicate plane state
73  * @plane: drm plane
74  *
75  * Allocates and returns a copy of the plane state (both common and
76  * Intel-specific) for the specified plane.
77  *
78  * Returns: The newly allocated plane state, or NULL on failure.
79  */
80 struct drm_plane_state *
81 intel_plane_duplicate_state(struct drm_plane *plane)
82 {
83 	struct drm_plane_state *state;
84 	struct intel_plane_state *intel_state;
85 
86 	intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL);
87 
88 	if (!intel_state)
89 		return NULL;
90 
91 	state = &intel_state->base;
92 
93 	__drm_atomic_helper_plane_duplicate_state(plane, state);
94 
95 	intel_state->vma = NULL;
96 	intel_state->flags = 0;
97 
98 	return state;
99 }
100 
101 /**
102  * intel_plane_destroy_state - destroy plane state
103  * @plane: drm plane
104  * @state: state object to destroy
105  *
106  * Destroys the plane state (both common and Intel-specific) for the
107  * specified plane.
108  */
109 void
110 intel_plane_destroy_state(struct drm_plane *plane,
111 			  struct drm_plane_state *state)
112 {
113 	WARN_ON(to_intel_plane_state(state)->vma);
114 
115 	drm_atomic_helper_plane_destroy_state(plane, state);
116 }
117 
118 unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
119 				   const struct intel_plane_state *plane_state)
120 {
121 	const struct drm_framebuffer *fb = plane_state->base.fb;
122 	unsigned int cpp;
123 
124 	if (!plane_state->base.visible)
125 		return 0;
126 
127 	cpp = fb->format->cpp[0];
128 
129 	/*
130 	 * Based on HSD#:1408715493
131 	 * NV12 cpp == 4, P010 cpp == 8
132 	 *
133 	 * FIXME what is the logic behind this?
134 	 */
135 	if (fb->format->is_yuv && fb->format->num_planes > 1)
136 		cpp *= 4;
137 
138 	return cpp * crtc_state->pixel_rate;
139 }
140 
141 int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
142 					struct intel_crtc_state *new_crtc_state,
143 					const struct intel_plane_state *old_plane_state,
144 					struct intel_plane_state *new_plane_state)
145 {
146 	struct intel_plane *plane = to_intel_plane(new_plane_state->base.plane);
147 	int ret;
148 
149 	new_crtc_state->active_planes &= ~BIT(plane->id);
150 	new_crtc_state->nv12_planes &= ~BIT(plane->id);
151 	new_crtc_state->c8_planes &= ~BIT(plane->id);
152 	new_crtc_state->data_rate[plane->id] = 0;
153 	new_plane_state->base.visible = false;
154 
155 	if (!new_plane_state->base.crtc && !old_plane_state->base.crtc)
156 		return 0;
157 
158 	ret = plane->check_plane(new_crtc_state, new_plane_state);
159 	if (ret)
160 		return ret;
161 
162 	/* FIXME pre-g4x don't work like this */
163 	if (new_plane_state->base.visible)
164 		new_crtc_state->active_planes |= BIT(plane->id);
165 
166 	if (new_plane_state->base.visible &&
167 	    is_planar_yuv_format(new_plane_state->base.fb->format->format))
168 		new_crtc_state->nv12_planes |= BIT(plane->id);
169 
170 	if (new_plane_state->base.visible &&
171 	    new_plane_state->base.fb->format->format == DRM_FORMAT_C8)
172 		new_crtc_state->c8_planes |= BIT(plane->id);
173 
174 	if (new_plane_state->base.visible || old_plane_state->base.visible)
175 		new_crtc_state->update_planes |= BIT(plane->id);
176 
177 	new_crtc_state->data_rate[plane->id] =
178 		intel_plane_data_rate(new_crtc_state, new_plane_state);
179 
180 	return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
181 					       old_plane_state, new_plane_state);
182 }
183 
184 static struct intel_crtc *
185 get_crtc_from_states(const struct intel_plane_state *old_plane_state,
186 		     const struct intel_plane_state *new_plane_state)
187 {
188 	if (new_plane_state->base.crtc)
189 		return to_intel_crtc(new_plane_state->base.crtc);
190 
191 	if (old_plane_state->base.crtc)
192 		return to_intel_crtc(old_plane_state->base.crtc);
193 
194 	return NULL;
195 }
196 
197 static int intel_plane_atomic_check(struct drm_plane *_plane,
198 				    struct drm_plane_state *_new_plane_state)
199 {
200 	struct intel_plane *plane = to_intel_plane(_plane);
201 	struct intel_atomic_state *state =
202 		to_intel_atomic_state(_new_plane_state->state);
203 	struct intel_plane_state *new_plane_state =
204 		to_intel_plane_state(_new_plane_state);
205 	const struct intel_plane_state *old_plane_state =
206 		intel_atomic_get_old_plane_state(state, plane);
207 	struct intel_crtc *crtc =
208 		get_crtc_from_states(old_plane_state, new_plane_state);
209 	const struct intel_crtc_state *old_crtc_state;
210 	struct intel_crtc_state *new_crtc_state;
211 
212 	new_plane_state->base.visible = false;
213 	if (!crtc)
214 		return 0;
215 
216 	old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
217 	new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
218 
219 	return intel_plane_atomic_check_with_state(old_crtc_state,
220 						   new_crtc_state,
221 						   old_plane_state,
222 						   new_plane_state);
223 }
224 
225 static struct intel_plane *
226 skl_next_plane_to_commit(struct intel_atomic_state *state,
227 			 struct intel_crtc *crtc,
228 			 struct skl_ddb_entry entries_y[I915_MAX_PLANES],
229 			 struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
230 			 unsigned int *update_mask)
231 {
232 	struct intel_crtc_state *crtc_state =
233 		intel_atomic_get_new_crtc_state(state, crtc);
234 	struct intel_plane_state *plane_state;
235 	struct intel_plane *plane;
236 	int i;
237 
238 	if (*update_mask == 0)
239 		return NULL;
240 
241 	for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
242 		enum plane_id plane_id = plane->id;
243 
244 		if (crtc->pipe != plane->pipe ||
245 		    !(*update_mask & BIT(plane_id)))
246 			continue;
247 
248 		if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
249 						entries_y,
250 						I915_MAX_PLANES, plane_id) ||
251 		    skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
252 						entries_uv,
253 						I915_MAX_PLANES, plane_id))
254 			continue;
255 
256 		*update_mask &= ~BIT(plane_id);
257 		entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
258 		entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
259 
260 		return plane;
261 	}
262 
263 	/* should never happen */
264 	WARN_ON(1);
265 
266 	return NULL;
267 }
268 
269 void intel_update_plane(struct intel_plane *plane,
270 			const struct intel_crtc_state *crtc_state,
271 			const struct intel_plane_state *plane_state)
272 {
273 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
274 
275 	trace_intel_update_plane(&plane->base, crtc);
276 	plane->update_plane(plane, crtc_state, plane_state);
277 }
278 
279 void intel_update_slave(struct intel_plane *plane,
280 			const struct intel_crtc_state *crtc_state,
281 			const struct intel_plane_state *plane_state)
282 {
283 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
284 
285 	trace_intel_update_plane(&plane->base, crtc);
286 	plane->update_slave(plane, crtc_state, plane_state);
287 }
288 
289 void intel_disable_plane(struct intel_plane *plane,
290 			 const struct intel_crtc_state *crtc_state)
291 {
292 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
293 
294 	trace_intel_disable_plane(&plane->base, crtc);
295 	plane->disable_plane(plane, crtc_state);
296 }
297 
298 void skl_update_planes_on_crtc(struct intel_atomic_state *state,
299 			       struct intel_crtc *crtc)
300 {
301 	struct intel_crtc_state *old_crtc_state =
302 		intel_atomic_get_old_crtc_state(state, crtc);
303 	struct intel_crtc_state *new_crtc_state =
304 		intel_atomic_get_new_crtc_state(state, crtc);
305 	struct skl_ddb_entry entries_y[I915_MAX_PLANES];
306 	struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
307 	u32 update_mask = new_crtc_state->update_planes;
308 	struct intel_plane *plane;
309 
310 	memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
311 	       sizeof(old_crtc_state->wm.skl.plane_ddb_y));
312 	memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
313 	       sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
314 
315 	while ((plane = skl_next_plane_to_commit(state, crtc,
316 						 entries_y, entries_uv,
317 						 &update_mask))) {
318 		struct intel_plane_state *new_plane_state =
319 			intel_atomic_get_new_plane_state(state, plane);
320 
321 		if (new_plane_state->base.visible) {
322 			intel_update_plane(plane, new_crtc_state, new_plane_state);
323 		} else if (new_plane_state->slave) {
324 			struct intel_plane *master =
325 				new_plane_state->linked_plane;
326 
327 			/*
328 			 * We update the slave plane from this function because
329 			 * programming it from the master plane's update_plane
330 			 * callback runs into issues when the Y plane is
331 			 * reassigned, disabled or used by a different plane.
332 			 *
333 			 * The slave plane is updated with the master plane's
334 			 * plane_state.
335 			 */
336 			new_plane_state =
337 				intel_atomic_get_new_plane_state(state, master);
338 
339 			intel_update_slave(plane, new_crtc_state, new_plane_state);
340 		} else {
341 			intel_disable_plane(plane, new_crtc_state);
342 		}
343 	}
344 }
345 
346 void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
347 				struct intel_crtc *crtc)
348 {
349 	struct intel_crtc_state *new_crtc_state =
350 		intel_atomic_get_new_crtc_state(state, crtc);
351 	u32 update_mask = new_crtc_state->update_planes;
352 	struct intel_plane_state *new_plane_state;
353 	struct intel_plane *plane;
354 	int i;
355 
356 	for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
357 		if (crtc->pipe != plane->pipe ||
358 		    !(update_mask & BIT(plane->id)))
359 			continue;
360 
361 		if (new_plane_state->base.visible)
362 			intel_update_plane(plane, new_crtc_state, new_plane_state);
363 		else
364 			intel_disable_plane(plane, new_crtc_state);
365 	}
366 }
367 
368 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
369 	.prepare_fb = intel_prepare_plane_fb,
370 	.cleanup_fb = intel_cleanup_plane_fb,
371 	.atomic_check = intel_plane_atomic_check,
372 };
373