Merge drm/drm-next into drm-intel-next-queued
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / 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 "intel_drv.h"
39
40 struct intel_plane *intel_plane_alloc(void)
41 {
42         struct intel_plane_state *plane_state;
43         struct intel_plane *plane;
44
45         plane = kzalloc(sizeof(*plane), GFP_KERNEL);
46         if (!plane)
47                 return ERR_PTR(-ENOMEM);
48
49         plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
50         if (!plane_state) {
51                 kfree(plane);
52                 return ERR_PTR(-ENOMEM);
53         }
54
55         __drm_atomic_helper_plane_reset(&plane->base, &plane_state->base);
56         plane_state->scaler_id = -1;
57
58         return plane;
59 }
60
61 void intel_plane_free(struct intel_plane *plane)
62 {
63         intel_plane_destroy_state(&plane->base, plane->base.state);
64         kfree(plane);
65 }
66
67 /**
68  * intel_plane_duplicate_state - duplicate plane state
69  * @plane: drm plane
70  *
71  * Allocates and returns a copy of the plane state (both common and
72  * Intel-specific) for the specified plane.
73  *
74  * Returns: The newly allocated plane state, or NULL on failure.
75  */
76 struct drm_plane_state *
77 intel_plane_duplicate_state(struct drm_plane *plane)
78 {
79         struct drm_plane_state *state;
80         struct intel_plane_state *intel_state;
81
82         intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL);
83
84         if (!intel_state)
85                 return NULL;
86
87         state = &intel_state->base;
88
89         __drm_atomic_helper_plane_duplicate_state(plane, state);
90
91         intel_state->vma = NULL;
92         intel_state->flags = 0;
93
94         return state;
95 }
96
97 /**
98  * intel_plane_destroy_state - destroy plane state
99  * @plane: drm plane
100  * @state: state object to destroy
101  *
102  * Destroys the plane state (both common and Intel-specific) for the
103  * specified plane.
104  */
105 void
106 intel_plane_destroy_state(struct drm_plane *plane,
107                           struct drm_plane_state *state)
108 {
109         WARN_ON(to_intel_plane_state(state)->vma);
110
111         drm_atomic_helper_plane_destroy_state(plane, state);
112 }
113
114 int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
115                                         struct intel_crtc_state *new_crtc_state,
116                                         const struct intel_plane_state *old_plane_state,
117                                         struct intel_plane_state *new_plane_state)
118 {
119         struct intel_plane *plane = to_intel_plane(new_plane_state->base.plane);
120         int ret;
121
122         new_crtc_state->active_planes &= ~BIT(plane->id);
123         new_crtc_state->nv12_planes &= ~BIT(plane->id);
124         new_crtc_state->c8_planes &= ~BIT(plane->id);
125         new_plane_state->base.visible = false;
126
127         if (!new_plane_state->base.crtc && !old_plane_state->base.crtc)
128                 return 0;
129
130         ret = plane->check_plane(new_crtc_state, new_plane_state);
131         if (ret)
132                 return ret;
133
134         /* FIXME pre-g4x don't work like this */
135         if (new_plane_state->base.visible)
136                 new_crtc_state->active_planes |= BIT(plane->id);
137
138         if (new_plane_state->base.visible &&
139             is_planar_yuv_format(new_plane_state->base.fb->format->format))
140                 new_crtc_state->nv12_planes |= BIT(plane->id);
141
142         if (new_plane_state->base.visible &&
143             new_plane_state->base.fb->format->format == DRM_FORMAT_C8)
144                 new_crtc_state->c8_planes |= BIT(plane->id);
145
146         if (new_plane_state->base.visible || old_plane_state->base.visible)
147                 new_crtc_state->update_planes |= BIT(plane->id);
148
149         return intel_plane_atomic_calc_changes(old_crtc_state,
150                                                &new_crtc_state->base,
151                                                old_plane_state,
152                                                &new_plane_state->base);
153 }
154
155 static int intel_plane_atomic_check(struct drm_plane *plane,
156                                     struct drm_plane_state *new_plane_state)
157 {
158         struct drm_atomic_state *state = new_plane_state->state;
159         const struct drm_plane_state *old_plane_state =
160                 drm_atomic_get_old_plane_state(state, plane);
161         struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc;
162         const struct drm_crtc_state *old_crtc_state;
163         struct drm_crtc_state *new_crtc_state;
164
165         new_plane_state->visible = false;
166         if (!crtc)
167                 return 0;
168
169         old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
170         new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
171
172         return intel_plane_atomic_check_with_state(to_intel_crtc_state(old_crtc_state),
173                                                    to_intel_crtc_state(new_crtc_state),
174                                                    to_intel_plane_state(old_plane_state),
175                                                    to_intel_plane_state(new_plane_state));
176 }
177
178 static struct intel_plane *
179 skl_next_plane_to_commit(struct intel_atomic_state *state,
180                          struct intel_crtc *crtc,
181                          struct skl_ddb_entry entries_y[I915_MAX_PLANES],
182                          struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
183                          unsigned int *update_mask)
184 {
185         struct intel_crtc_state *crtc_state =
186                 intel_atomic_get_new_crtc_state(state, crtc);
187         struct intel_plane_state *plane_state;
188         struct intel_plane *plane;
189         int i;
190
191         if (*update_mask == 0)
192                 return NULL;
193
194         for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
195                 enum plane_id plane_id = plane->id;
196
197                 if (crtc->pipe != plane->pipe ||
198                     !(*update_mask & BIT(plane_id)))
199                         continue;
200
201                 if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
202                                                 entries_y,
203                                                 I915_MAX_PLANES, plane_id) ||
204                     skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
205                                                 entries_uv,
206                                                 I915_MAX_PLANES, plane_id))
207                         continue;
208
209                 *update_mask &= ~BIT(plane_id);
210                 entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
211                 entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
212
213                 return plane;
214         }
215
216         /* should never happen */
217         WARN_ON(1);
218
219         return NULL;
220 }
221
222 void intel_update_plane(struct intel_plane *plane,
223                         const struct intel_crtc_state *crtc_state,
224                         const struct intel_plane_state *plane_state)
225 {
226         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
227
228         trace_intel_update_plane(&plane->base, crtc);
229         plane->update_plane(plane, crtc_state, plane_state);
230 }
231
232 void intel_update_slave(struct intel_plane *plane,
233                         const struct intel_crtc_state *crtc_state,
234                         const struct intel_plane_state *plane_state)
235 {
236         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
237
238         trace_intel_update_plane(&plane->base, crtc);
239         plane->update_slave(plane, crtc_state, plane_state);
240 }
241
242 void intel_disable_plane(struct intel_plane *plane,
243                          const struct intel_crtc_state *crtc_state)
244 {
245         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
246
247         trace_intel_disable_plane(&plane->base, crtc);
248         plane->disable_plane(plane, crtc_state);
249 }
250
251 void skl_update_planes_on_crtc(struct intel_atomic_state *state,
252                                struct intel_crtc *crtc)
253 {
254         struct intel_crtc_state *old_crtc_state =
255                 intel_atomic_get_old_crtc_state(state, crtc);
256         struct intel_crtc_state *new_crtc_state =
257                 intel_atomic_get_new_crtc_state(state, crtc);
258         struct skl_ddb_entry entries_y[I915_MAX_PLANES];
259         struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
260         u32 update_mask = new_crtc_state->update_planes;
261         struct intel_plane *plane;
262
263         memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
264                sizeof(old_crtc_state->wm.skl.plane_ddb_y));
265         memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
266                sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
267
268         while ((plane = skl_next_plane_to_commit(state, crtc,
269                                                  entries_y, entries_uv,
270                                                  &update_mask))) {
271                 struct intel_plane_state *new_plane_state =
272                         intel_atomic_get_new_plane_state(state, plane);
273
274                 if (new_plane_state->base.visible) {
275                         intel_update_plane(plane, new_crtc_state, new_plane_state);
276                 } else if (new_plane_state->slave) {
277                         struct intel_plane *master =
278                                 new_plane_state->linked_plane;
279
280                         /*
281                          * We update the slave plane from this function because
282                          * programming it from the master plane's update_plane
283                          * callback runs into issues when the Y plane is
284                          * reassigned, disabled or used by a different plane.
285                          *
286                          * The slave plane is updated with the master plane's
287                          * plane_state.
288                          */
289                         new_plane_state =
290                                 intel_atomic_get_new_plane_state(state, master);
291
292                         intel_update_slave(plane, new_crtc_state, new_plane_state);
293                 } else {
294                         intel_disable_plane(plane, new_crtc_state);
295                 }
296         }
297 }
298
299 void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
300                                 struct intel_crtc *crtc)
301 {
302         struct intel_crtc_state *new_crtc_state =
303                 intel_atomic_get_new_crtc_state(state, crtc);
304         u32 update_mask = new_crtc_state->update_planes;
305         struct intel_plane_state *new_plane_state;
306         struct intel_plane *plane;
307         int i;
308
309         for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
310                 if (crtc->pipe != plane->pipe ||
311                     !(update_mask & BIT(plane->id)))
312                         continue;
313
314                 if (new_plane_state->base.visible)
315                         intel_update_plane(plane, new_crtc_state, new_plane_state);
316                 else
317                         intel_disable_plane(plane, new_crtc_state);
318         }
319 }
320
321 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
322         .prepare_fb = intel_prepare_plane_fb,
323         .cleanup_fb = intel_cleanup_plane_fb,
324         .atomic_check = intel_plane_atomic_check,
325 };
326
327 /**
328  * intel_plane_atomic_get_property - fetch plane property value
329  * @plane: plane to fetch property for
330  * @state: state containing the property value
331  * @property: property to look up
332  * @val: pointer to write property value into
333  *
334  * The DRM core does not store shadow copies of properties for
335  * atomic-capable drivers.  This entrypoint is used to fetch
336  * the current value of a driver-specific plane property.
337  */
338 int
339 intel_plane_atomic_get_property(struct drm_plane *plane,
340                                 const struct drm_plane_state *state,
341                                 struct drm_property *property,
342                                 u64 *val)
343 {
344         DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
345                       property->base.id, property->name);
346         return -EINVAL;
347 }
348
349 /**
350  * intel_plane_atomic_set_property - set plane property value
351  * @plane: plane to set property for
352  * @state: state to update property value in
353  * @property: property to set
354  * @val: value to set property to
355  *
356  * Writes the specified property value for a plane into the provided atomic
357  * state object.
358  *
359  * Returns 0 on success, -EINVAL on unrecognized properties
360  */
361 int
362 intel_plane_atomic_set_property(struct drm_plane *plane,
363                                 struct drm_plane_state *state,
364                                 struct drm_property *property,
365                                 u64 val)
366 {
367         DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
368                       property->base.id, property->name);
369         return -EINVAL;
370 }