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
intel_plane_alloc(void)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
intel_plane_free(struct intel_plane * plane)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 *
intel_plane_duplicate_state(struct drm_plane * plane)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
intel_plane_destroy_state(struct drm_plane * plane,struct drm_plane_state * state)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
intel_plane_data_rate(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)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
intel_plane_atomic_check_with_state(const struct intel_crtc_state * old_crtc_state,struct intel_crtc_state * new_crtc_state,const struct intel_plane_state * old_plane_state,struct intel_plane_state * new_plane_state)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 *
get_crtc_from_states(const struct intel_plane_state * old_plane_state,const struct intel_plane_state * new_plane_state)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
intel_plane_atomic_check(struct drm_plane * _plane,struct drm_plane_state * _new_plane_state)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 *
skl_next_plane_to_commit(struct intel_atomic_state * state,struct intel_crtc * crtc,struct skl_ddb_entry entries_y[I915_MAX_PLANES],struct skl_ddb_entry entries_uv[I915_MAX_PLANES],unsigned int * update_mask)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
intel_update_plane(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)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
intel_update_slave(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)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
intel_disable_plane(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)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
skl_update_planes_on_crtc(struct intel_atomic_state * state,struct intel_crtc * crtc)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
i9xx_update_planes_on_crtc(struct intel_atomic_state * state,struct intel_crtc * crtc)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