drm/i915: Extract intel_cdclk_state
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / display / intel_atomic_plane.c
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 static void intel_plane_state_reset(struct intel_plane_state *plane_state,
45                                     struct intel_plane *plane)
46 {
47         memset(plane_state, 0, sizeof(*plane_state));
48
49         __drm_atomic_helper_plane_state_reset(&plane_state->uapi, &plane->base);
50
51         plane_state->scaler_id = -1;
52 }
53
54 struct intel_plane *intel_plane_alloc(void)
55 {
56         struct intel_plane_state *plane_state;
57         struct intel_plane *plane;
58
59         plane = kzalloc(sizeof(*plane), GFP_KERNEL);
60         if (!plane)
61                 return ERR_PTR(-ENOMEM);
62
63         plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
64         if (!plane_state) {
65                 kfree(plane);
66                 return ERR_PTR(-ENOMEM);
67         }
68
69         intel_plane_state_reset(plane_state, plane);
70
71         plane->base.state = &plane_state->uapi;
72
73         return plane;
74 }
75
76 void intel_plane_free(struct intel_plane *plane)
77 {
78         intel_plane_destroy_state(&plane->base, plane->base.state);
79         kfree(plane);
80 }
81
82 /**
83  * intel_plane_duplicate_state - duplicate plane state
84  * @plane: drm plane
85  *
86  * Allocates and returns a copy of the plane state (both common and
87  * Intel-specific) for the specified plane.
88  *
89  * Returns: The newly allocated plane state, or NULL on failure.
90  */
91 struct drm_plane_state *
92 intel_plane_duplicate_state(struct drm_plane *plane)
93 {
94         struct intel_plane_state *intel_state;
95
96         intel_state = to_intel_plane_state(plane->state);
97         intel_state = kmemdup(intel_state, sizeof(*intel_state), GFP_KERNEL);
98
99         if (!intel_state)
100                 return NULL;
101
102         __drm_atomic_helper_plane_duplicate_state(plane, &intel_state->uapi);
103
104         intel_state->vma = NULL;
105         intel_state->flags = 0;
106
107         /* add reference to fb */
108         if (intel_state->hw.fb)
109                 drm_framebuffer_get(intel_state->hw.fb);
110
111         return &intel_state->uapi;
112 }
113
114 /**
115  * intel_plane_destroy_state - destroy plane state
116  * @plane: drm plane
117  * @state: state object to destroy
118  *
119  * Destroys the plane state (both common and Intel-specific) for the
120  * specified plane.
121  */
122 void
123 intel_plane_destroy_state(struct drm_plane *plane,
124                           struct drm_plane_state *state)
125 {
126         struct intel_plane_state *plane_state = to_intel_plane_state(state);
127         WARN_ON(plane_state->vma);
128
129         __drm_atomic_helper_plane_destroy_state(&plane_state->uapi);
130         if (plane_state->hw.fb)
131                 drm_framebuffer_put(plane_state->hw.fb);
132         kfree(plane_state);
133 }
134
135 unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
136                                    const struct intel_plane_state *plane_state)
137 {
138         const struct drm_framebuffer *fb = plane_state->hw.fb;
139         unsigned int cpp;
140
141         if (!plane_state->uapi.visible)
142                 return 0;
143
144         cpp = fb->format->cpp[0];
145
146         /*
147          * Based on HSD#:1408715493
148          * NV12 cpp == 4, P010 cpp == 8
149          *
150          * FIXME what is the logic behind this?
151          */
152         if (fb->format->is_yuv && fb->format->num_planes > 1)
153                 cpp *= 4;
154
155         return cpp * crtc_state->pixel_rate;
156 }
157
158 bool intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
159                                 struct intel_plane *plane)
160 {
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;
168
169         if (!plane_state->uapi.visible || !plane->min_cdclk)
170                 return false;
171
172         crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
173
174         crtc_state->min_cdclk[plane->id] =
175                 plane->min_cdclk(crtc_state, plane_state);
176
177         /*
178          * Does the cdclk need to be bumbed up?
179          *
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).
186          */
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);
193                 return true;
194         }
195
196         return false;
197 }
198
199 static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state)
200 {
201         if (plane_state->hw.fb)
202                 drm_framebuffer_put(plane_state->hw.fb);
203
204         memset(&plane_state->hw, 0, sizeof(plane_state->hw));
205 }
206
207 void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
208                                        const struct intel_plane_state *from_plane_state)
209 {
210         intel_plane_clear_hw_state(plane_state);
211
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);
216
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;
223 }
224
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)
229 {
230         struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
231         const struct drm_framebuffer *fb = new_plane_state->hw.fb;
232         int ret;
233
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;
240
241         if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc)
242                 return 0;
243
244         ret = plane->check_plane(new_crtc_state, new_plane_state);
245         if (ret)
246                 return ret;
247
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);
251
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);
255
256         if (new_plane_state->uapi.visible &&
257             fb->format->format == DRM_FORMAT_C8)
258                 new_crtc_state->c8_planes |= BIT(plane->id);
259
260         if (new_plane_state->uapi.visible || old_plane_state->uapi.visible)
261                 new_crtc_state->update_planes |= BIT(plane->id);
262
263         new_crtc_state->data_rate[plane->id] =
264                 intel_plane_data_rate(new_crtc_state, new_plane_state);
265
266         return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
267                                                old_plane_state, new_plane_state);
268 }
269
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)
273 {
274         if (new_plane_state->uapi.crtc)
275                 return to_intel_crtc(new_plane_state->uapi.crtc);
276
277         if (old_plane_state->uapi.crtc)
278                 return to_intel_crtc(old_plane_state->uapi.crtc);
279
280         return NULL;
281 }
282
283 int intel_plane_atomic_check(struct intel_atomic_state *state,
284                              struct intel_plane *plane)
285 {
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;
294
295         intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state);
296         new_plane_state->uapi.visible = false;
297         if (!crtc)
298                 return 0;
299
300         old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
301         new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
302
303         return intel_plane_atomic_check_with_state(old_crtc_state,
304                                                    new_crtc_state,
305                                                    old_plane_state,
306                                                    new_plane_state);
307 }
308
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)
315 {
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;
320         int i;
321
322         if (*update_mask == 0)
323                 return NULL;
324
325         for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
326                 enum plane_id plane_id = plane->id;
327
328                 if (crtc->pipe != plane->pipe ||
329                     !(*update_mask & BIT(plane_id)))
330                         continue;
331
332                 if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
333                                                 entries_y,
334                                                 I915_MAX_PLANES, plane_id) ||
335                     skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
336                                                 entries_uv,
337                                                 I915_MAX_PLANES, plane_id))
338                         continue;
339
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];
343
344                 return plane;
345         }
346
347         /* should never happen */
348         WARN_ON(1);
349
350         return NULL;
351 }
352
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)
356 {
357         struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
358
359         trace_intel_update_plane(&plane->base, crtc);
360         plane->update_plane(plane, crtc_state, plane_state);
361 }
362
363 void intel_disable_plane(struct intel_plane *plane,
364                          const struct intel_crtc_state *crtc_state)
365 {
366         struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
367
368         trace_intel_disable_plane(&plane->base, crtc);
369         plane->disable_plane(plane, crtc_state);
370 }
371
372 void skl_update_planes_on_crtc(struct intel_atomic_state *state,
373                                struct intel_crtc *crtc)
374 {
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;
383
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));
388
389         while ((plane = skl_next_plane_to_commit(state, crtc,
390                                                  entries_y, entries_uv,
391                                                  &update_mask))) {
392                 struct intel_plane_state *new_plane_state =
393                         intel_atomic_get_new_plane_state(state, plane);
394
395                 if (new_plane_state->uapi.visible ||
396                     new_plane_state->planar_slave) {
397                         intel_update_plane(plane, new_crtc_state, new_plane_state);
398                 } else {
399                         intel_disable_plane(plane, new_crtc_state);
400                 }
401         }
402 }
403
404 void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
405                                 struct intel_crtc *crtc)
406 {
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;
412         int i;
413
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)))
417                         continue;
418
419                 if (new_plane_state->uapi.visible)
420                         intel_update_plane(plane, new_crtc_state, new_plane_state);
421                 else
422                         intel_disable_plane(plane, new_crtc_state);
423         }
424 }
425
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,
429 };