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 	const struct drm_framebuffer *fb = new_plane_state->base.fb;
148 	int ret;
149 
150 	new_crtc_state->active_planes &= ~BIT(plane->id);
151 	new_crtc_state->nv12_planes &= ~BIT(plane->id);
152 	new_crtc_state->c8_planes &= ~BIT(plane->id);
153 	new_crtc_state->data_rate[plane->id] = 0;
154 	new_plane_state->base.visible = false;
155 
156 	if (!new_plane_state->base.crtc && !old_plane_state->base.crtc)
157 		return 0;
158 
159 	ret = plane->check_plane(new_crtc_state, new_plane_state);
160 	if (ret)
161 		return ret;
162 
163 	/* FIXME pre-g4x don't work like this */
164 	if (new_plane_state->base.visible)
165 		new_crtc_state->active_planes |= BIT(plane->id);
166 
167 	if (new_plane_state->base.visible &&
168 	    drm_format_info_is_yuv_semiplanar(fb->format))
169 		new_crtc_state->nv12_planes |= BIT(plane->id);
170 
171 	if (new_plane_state->base.visible &&
172 	    fb->format->format == DRM_FORMAT_C8)
173 		new_crtc_state->c8_planes |= BIT(plane->id);
174 
175 	if (new_plane_state->base.visible || old_plane_state->base.visible)
176 		new_crtc_state->update_planes |= BIT(plane->id);
177 
178 	new_crtc_state->data_rate[plane->id] =
179 		intel_plane_data_rate(new_crtc_state, new_plane_state);
180 
181 	return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
182 					       old_plane_state, new_plane_state);
183 }
184 
185 static struct intel_crtc *
186 get_crtc_from_states(const struct intel_plane_state *old_plane_state,
187 		     const struct intel_plane_state *new_plane_state)
188 {
189 	if (new_plane_state->base.crtc)
190 		return to_intel_crtc(new_plane_state->base.crtc);
191 
192 	if (old_plane_state->base.crtc)
193 		return to_intel_crtc(old_plane_state->base.crtc);
194 
195 	return NULL;
196 }
197 
198 static int intel_plane_atomic_check(struct drm_plane *_plane,
199 				    struct drm_plane_state *_new_plane_state)
200 {
201 	struct intel_plane *plane = to_intel_plane(_plane);
202 	struct intel_atomic_state *state =
203 		to_intel_atomic_state(_new_plane_state->state);
204 	struct intel_plane_state *new_plane_state =
205 		to_intel_plane_state(_new_plane_state);
206 	const struct intel_plane_state *old_plane_state =
207 		intel_atomic_get_old_plane_state(state, plane);
208 	struct intel_crtc *crtc =
209 		get_crtc_from_states(old_plane_state, new_plane_state);
210 	const struct intel_crtc_state *old_crtc_state;
211 	struct intel_crtc_state *new_crtc_state;
212 
213 	new_plane_state->base.visible = false;
214 	if (!crtc)
215 		return 0;
216 
217 	old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
218 	new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
219 
220 	return intel_plane_atomic_check_with_state(old_crtc_state,
221 						   new_crtc_state,
222 						   old_plane_state,
223 						   new_plane_state);
224 }
225 
226 static struct intel_plane *
227 skl_next_plane_to_commit(struct intel_atomic_state *state,
228 			 struct intel_crtc *crtc,
229 			 struct skl_ddb_entry entries_y[I915_MAX_PLANES],
230 			 struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
231 			 unsigned int *update_mask)
232 {
233 	struct intel_crtc_state *crtc_state =
234 		intel_atomic_get_new_crtc_state(state, crtc);
235 	struct intel_plane_state *plane_state;
236 	struct intel_plane *plane;
237 	int i;
238 
239 	if (*update_mask == 0)
240 		return NULL;
241 
242 	for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
243 		enum plane_id plane_id = plane->id;
244 
245 		if (crtc->pipe != plane->pipe ||
246 		    !(*update_mask & BIT(plane_id)))
247 			continue;
248 
249 		if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
250 						entries_y,
251 						I915_MAX_PLANES, plane_id) ||
252 		    skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
253 						entries_uv,
254 						I915_MAX_PLANES, plane_id))
255 			continue;
256 
257 		*update_mask &= ~BIT(plane_id);
258 		entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
259 		entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
260 
261 		return plane;
262 	}
263 
264 	/* should never happen */
265 	WARN_ON(1);
266 
267 	return NULL;
268 }
269 
270 void intel_update_plane(struct intel_plane *plane,
271 			const struct intel_crtc_state *crtc_state,
272 			const struct intel_plane_state *plane_state)
273 {
274 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
275 
276 	trace_intel_update_plane(&plane->base, crtc);
277 	plane->update_plane(plane, crtc_state, plane_state);
278 }
279 
280 void intel_update_slave(struct intel_plane *plane,
281 			const struct intel_crtc_state *crtc_state,
282 			const struct intel_plane_state *plane_state)
283 {
284 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
285 
286 	trace_intel_update_plane(&plane->base, crtc);
287 	plane->update_slave(plane, crtc_state, plane_state);
288 }
289 
290 void intel_disable_plane(struct intel_plane *plane,
291 			 const struct intel_crtc_state *crtc_state)
292 {
293 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
294 
295 	trace_intel_disable_plane(&plane->base, crtc);
296 	plane->disable_plane(plane, crtc_state);
297 }
298 
299 void skl_update_planes_on_crtc(struct intel_atomic_state *state,
300 			       struct intel_crtc *crtc)
301 {
302 	struct intel_crtc_state *old_crtc_state =
303 		intel_atomic_get_old_crtc_state(state, crtc);
304 	struct intel_crtc_state *new_crtc_state =
305 		intel_atomic_get_new_crtc_state(state, crtc);
306 	struct skl_ddb_entry entries_y[I915_MAX_PLANES];
307 	struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
308 	u32 update_mask = new_crtc_state->update_planes;
309 	struct intel_plane *plane;
310 
311 	memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
312 	       sizeof(old_crtc_state->wm.skl.plane_ddb_y));
313 	memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
314 	       sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
315 
316 	while ((plane = skl_next_plane_to_commit(state, crtc,
317 						 entries_y, entries_uv,
318 						 &update_mask))) {
319 		struct intel_plane_state *new_plane_state =
320 			intel_atomic_get_new_plane_state(state, plane);
321 
322 		if (new_plane_state->base.visible) {
323 			intel_update_plane(plane, new_crtc_state, new_plane_state);
324 		} else if (new_plane_state->planar_slave) {
325 			struct intel_plane *master =
326 				new_plane_state->planar_linked_plane;
327 
328 			/*
329 			 * We update the slave plane from this function because
330 			 * programming it from the master plane's update_plane
331 			 * callback runs into issues when the Y plane is
332 			 * reassigned, disabled or used by a different plane.
333 			 *
334 			 * The slave plane is updated with the master plane's
335 			 * plane_state.
336 			 */
337 			new_plane_state =
338 				intel_atomic_get_new_plane_state(state, master);
339 
340 			intel_update_slave(plane, new_crtc_state, new_plane_state);
341 		} else {
342 			intel_disable_plane(plane, new_crtc_state);
343 		}
344 	}
345 }
346 
347 void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
348 				struct intel_crtc *crtc)
349 {
350 	struct intel_crtc_state *new_crtc_state =
351 		intel_atomic_get_new_crtc_state(state, crtc);
352 	u32 update_mask = new_crtc_state->update_planes;
353 	struct intel_plane_state *new_plane_state;
354 	struct intel_plane *plane;
355 	int i;
356 
357 	for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
358 		if (crtc->pipe != plane->pipe ||
359 		    !(update_mask & BIT(plane->id)))
360 			continue;
361 
362 		if (new_plane_state->base.visible)
363 			intel_update_plane(plane, new_crtc_state, new_plane_state);
364 		else
365 			intel_disable_plane(plane, new_crtc_state);
366 	}
367 }
368 
369 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
370 	.prepare_fb = intel_prepare_plane_fb,
371 	.cleanup_fb = intel_cleanup_plane_fb,
372 	.atomic_check = intel_plane_atomic_check,
373 };
374