2 * Copyright © 2014 Intel Corporation
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:
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
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.
25 * DOC: atomic plane helpers
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.
34 #include <drm/drm_atomic_helper.h>
35 #include <drm/drm_fourcc.h>
36 #include <drm/drm_plane_helper.h>
38 #include "i915_trace.h"
39 #include "intel_atomic_plane.h"
40 #include "intel_display_types.h"
42 #include "intel_sprite.h"
44 static void intel_plane_state_reset(struct intel_plane_state *plane_state,
45 struct intel_plane *plane)
47 memset(plane_state, 0, sizeof(*plane_state));
49 __drm_atomic_helper_plane_state_reset(&plane_state->uapi, &plane->base);
51 plane_state->scaler_id = -1;
54 struct intel_plane *intel_plane_alloc(void)
56 struct intel_plane_state *plane_state;
57 struct intel_plane *plane;
59 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
61 return ERR_PTR(-ENOMEM);
63 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
66 return ERR_PTR(-ENOMEM);
69 intel_plane_state_reset(plane_state, plane);
71 plane->base.state = &plane_state->uapi;
76 void intel_plane_free(struct intel_plane *plane)
78 intel_plane_destroy_state(&plane->base, plane->base.state);
83 * intel_plane_duplicate_state - duplicate plane state
86 * Allocates and returns a copy of the plane state (both common and
87 * Intel-specific) for the specified plane.
89 * Returns: The newly allocated plane state, or NULL on failure.
91 struct drm_plane_state *
92 intel_plane_duplicate_state(struct drm_plane *plane)
94 struct intel_plane_state *intel_state;
96 intel_state = to_intel_plane_state(plane->state);
97 intel_state = kmemdup(intel_state, sizeof(*intel_state), GFP_KERNEL);
102 __drm_atomic_helper_plane_duplicate_state(plane, &intel_state->uapi);
104 intel_state->vma = NULL;
105 intel_state->flags = 0;
107 /* add reference to fb */
108 if (intel_state->hw.fb)
109 drm_framebuffer_get(intel_state->hw.fb);
111 return &intel_state->uapi;
115 * intel_plane_destroy_state - destroy plane state
117 * @state: state object to destroy
119 * Destroys the plane state (both common and Intel-specific) for the
123 intel_plane_destroy_state(struct drm_plane *plane,
124 struct drm_plane_state *state)
126 struct intel_plane_state *plane_state = to_intel_plane_state(state);
127 WARN_ON(plane_state->vma);
129 __drm_atomic_helper_plane_destroy_state(&plane_state->uapi);
130 if (plane_state->hw.fb)
131 drm_framebuffer_put(plane_state->hw.fb);
135 unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
136 const struct intel_plane_state *plane_state)
138 const struct drm_framebuffer *fb = plane_state->hw.fb;
141 if (!plane_state->uapi.visible)
144 cpp = fb->format->cpp[0];
147 * Based on HSD#:1408715493
148 * NV12 cpp == 4, P010 cpp == 8
150 * FIXME what is the logic behind this?
152 if (fb->format->is_yuv && fb->format->num_planes > 1)
155 return cpp * crtc_state->pixel_rate;
158 bool intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
159 struct intel_plane *plane)
161 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
162 const struct intel_cdclk_state *cdclk_state =
163 &dev_priv->cdclk_state;
164 const struct intel_plane_state *plane_state =
165 intel_atomic_get_new_plane_state(state, plane);
166 struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc);
167 struct intel_crtc_state *crtc_state;
169 if (!plane_state->uapi.visible || !plane->min_cdclk)
172 crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
174 crtc_state->min_cdclk[plane->id] =
175 plane->min_cdclk(crtc_state, plane_state);
178 * Does the cdclk need to be bumbed up?
180 * Note: we obviously need to be called before the new
181 * cdclk frequency is calculated so state->cdclk.logical
182 * hasn't been populated yet. Hence we look at the old
183 * cdclk state under dev_priv->cdclk.logical. This is
184 * safe as long we hold at least one crtc mutex (which
185 * must be true since we have crtc_state).
187 if (crtc_state->min_cdclk[plane->id] > cdclk_state->logical.cdclk) {
188 drm_dbg_kms(&dev_priv->drm,
189 "[PLANE:%d:%s] min_cdclk (%d kHz) > logical cdclk (%d kHz)\n",
190 plane->base.base.id, plane->base.name,
191 crtc_state->min_cdclk[plane->id],
192 cdclk_state->logical.cdclk);
199 static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state)
201 if (plane_state->hw.fb)
202 drm_framebuffer_put(plane_state->hw.fb);
204 memset(&plane_state->hw, 0, sizeof(plane_state->hw));
207 void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
208 const struct intel_plane_state *from_plane_state)
210 intel_plane_clear_hw_state(plane_state);
212 plane_state->hw.crtc = from_plane_state->uapi.crtc;
213 plane_state->hw.fb = from_plane_state->uapi.fb;
214 if (plane_state->hw.fb)
215 drm_framebuffer_get(plane_state->hw.fb);
217 plane_state->hw.alpha = from_plane_state->uapi.alpha;
218 plane_state->hw.pixel_blend_mode =
219 from_plane_state->uapi.pixel_blend_mode;
220 plane_state->hw.rotation = from_plane_state->uapi.rotation;
221 plane_state->hw.color_encoding = from_plane_state->uapi.color_encoding;
222 plane_state->hw.color_range = from_plane_state->uapi.color_range;
225 int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
226 struct intel_crtc_state *new_crtc_state,
227 const struct intel_plane_state *old_plane_state,
228 struct intel_plane_state *new_plane_state)
230 struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
231 const struct drm_framebuffer *fb = new_plane_state->hw.fb;
234 new_crtc_state->active_planes &= ~BIT(plane->id);
235 new_crtc_state->nv12_planes &= ~BIT(plane->id);
236 new_crtc_state->c8_planes &= ~BIT(plane->id);
237 new_crtc_state->data_rate[plane->id] = 0;
238 new_crtc_state->min_cdclk[plane->id] = 0;
239 new_plane_state->uapi.visible = false;
241 if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc)
244 ret = plane->check_plane(new_crtc_state, new_plane_state);
248 /* FIXME pre-g4x don't work like this */
249 if (new_plane_state->uapi.visible)
250 new_crtc_state->active_planes |= BIT(plane->id);
252 if (new_plane_state->uapi.visible &&
253 intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
254 new_crtc_state->nv12_planes |= BIT(plane->id);
256 if (new_plane_state->uapi.visible &&
257 fb->format->format == DRM_FORMAT_C8)
258 new_crtc_state->c8_planes |= BIT(plane->id);
260 if (new_plane_state->uapi.visible || old_plane_state->uapi.visible)
261 new_crtc_state->update_planes |= BIT(plane->id);
263 new_crtc_state->data_rate[plane->id] =
264 intel_plane_data_rate(new_crtc_state, new_plane_state);
266 return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
267 old_plane_state, new_plane_state);
270 static struct intel_crtc *
271 get_crtc_from_states(const struct intel_plane_state *old_plane_state,
272 const struct intel_plane_state *new_plane_state)
274 if (new_plane_state->uapi.crtc)
275 return to_intel_crtc(new_plane_state->uapi.crtc);
277 if (old_plane_state->uapi.crtc)
278 return to_intel_crtc(old_plane_state->uapi.crtc);
283 int intel_plane_atomic_check(struct intel_atomic_state *state,
284 struct intel_plane *plane)
286 struct intel_plane_state *new_plane_state =
287 intel_atomic_get_new_plane_state(state, plane);
288 const struct intel_plane_state *old_plane_state =
289 intel_atomic_get_old_plane_state(state, plane);
290 struct intel_crtc *crtc =
291 get_crtc_from_states(old_plane_state, new_plane_state);
292 const struct intel_crtc_state *old_crtc_state;
293 struct intel_crtc_state *new_crtc_state;
295 intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state);
296 new_plane_state->uapi.visible = false;
300 old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
301 new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
303 return intel_plane_atomic_check_with_state(old_crtc_state,
309 static struct intel_plane *
310 skl_next_plane_to_commit(struct intel_atomic_state *state,
311 struct intel_crtc *crtc,
312 struct skl_ddb_entry entries_y[I915_MAX_PLANES],
313 struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
314 unsigned int *update_mask)
316 struct intel_crtc_state *crtc_state =
317 intel_atomic_get_new_crtc_state(state, crtc);
318 struct intel_plane_state *plane_state;
319 struct intel_plane *plane;
322 if (*update_mask == 0)
325 for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
326 enum plane_id plane_id = plane->id;
328 if (crtc->pipe != plane->pipe ||
329 !(*update_mask & BIT(plane_id)))
332 if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
334 I915_MAX_PLANES, plane_id) ||
335 skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
337 I915_MAX_PLANES, plane_id))
340 *update_mask &= ~BIT(plane_id);
341 entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
342 entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
347 /* should never happen */
353 void intel_update_plane(struct intel_plane *plane,
354 const struct intel_crtc_state *crtc_state,
355 const struct intel_plane_state *plane_state)
357 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
359 trace_intel_update_plane(&plane->base, crtc);
360 plane->update_plane(plane, crtc_state, plane_state);
363 void intel_disable_plane(struct intel_plane *plane,
364 const struct intel_crtc_state *crtc_state)
366 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
368 trace_intel_disable_plane(&plane->base, crtc);
369 plane->disable_plane(plane, crtc_state);
372 void skl_update_planes_on_crtc(struct intel_atomic_state *state,
373 struct intel_crtc *crtc)
375 struct intel_crtc_state *old_crtc_state =
376 intel_atomic_get_old_crtc_state(state, crtc);
377 struct intel_crtc_state *new_crtc_state =
378 intel_atomic_get_new_crtc_state(state, crtc);
379 struct skl_ddb_entry entries_y[I915_MAX_PLANES];
380 struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
381 u32 update_mask = new_crtc_state->update_planes;
382 struct intel_plane *plane;
384 memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
385 sizeof(old_crtc_state->wm.skl.plane_ddb_y));
386 memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
387 sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
389 while ((plane = skl_next_plane_to_commit(state, crtc,
390 entries_y, entries_uv,
392 struct intel_plane_state *new_plane_state =
393 intel_atomic_get_new_plane_state(state, plane);
395 if (new_plane_state->uapi.visible ||
396 new_plane_state->planar_slave) {
397 intel_update_plane(plane, new_crtc_state, new_plane_state);
399 intel_disable_plane(plane, new_crtc_state);
404 void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
405 struct intel_crtc *crtc)
407 struct intel_crtc_state *new_crtc_state =
408 intel_atomic_get_new_crtc_state(state, crtc);
409 u32 update_mask = new_crtc_state->update_planes;
410 struct intel_plane_state *new_plane_state;
411 struct intel_plane *plane;
414 for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
415 if (crtc->pipe != plane->pipe ||
416 !(update_mask & BIT(plane->id)))
419 if (new_plane_state->uapi.visible)
420 intel_update_plane(plane, new_crtc_state, new_plane_state);
422 intel_disable_plane(plane, new_crtc_state);
426 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
427 .prepare_fb = intel_prepare_plane_fb,
428 .cleanup_fb = intel_cleanup_plane_fb,