]> Git Repo - J-linux.git/blob - drivers/gpu/drm/i915/intel_atomic_plane.c
Merge tag 'topic/drmp-cleanup-2019-01-02' of git://anongit.freedesktop.org/drm/drm...
[J-linux.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/drmP.h>
35 #include <drm/drm_atomic_helper.h>
36 #include <drm/drm_plane_helper.h>
37 #include "intel_drv.h"
38
39 struct intel_plane *intel_plane_alloc(void)
40 {
41         struct intel_plane_state *plane_state;
42         struct intel_plane *plane;
43
44         plane = kzalloc(sizeof(*plane), GFP_KERNEL);
45         if (!plane)
46                 return ERR_PTR(-ENOMEM);
47
48         plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
49         if (!plane_state) {
50                 kfree(plane);
51                 return ERR_PTR(-ENOMEM);
52         }
53
54         __drm_atomic_helper_plane_reset(&plane->base, &plane_state->base);
55         plane_state->scaler_id = -1;
56
57         return plane;
58 }
59
60 void intel_plane_free(struct intel_plane *plane)
61 {
62         intel_plane_destroy_state(&plane->base, plane->base.state);
63         kfree(plane);
64 }
65
66 /**
67  * intel_plane_duplicate_state - duplicate plane state
68  * @plane: drm plane
69  *
70  * Allocates and returns a copy of the plane state (both common and
71  * Intel-specific) for the specified plane.
72  *
73  * Returns: The newly allocated plane state, or NULL on failure.
74  */
75 struct drm_plane_state *
76 intel_plane_duplicate_state(struct drm_plane *plane)
77 {
78         struct drm_plane_state *state;
79         struct intel_plane_state *intel_state;
80
81         intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL);
82
83         if (!intel_state)
84                 return NULL;
85
86         state = &intel_state->base;
87
88         __drm_atomic_helper_plane_duplicate_state(plane, state);
89
90         intel_state->vma = NULL;
91         intel_state->flags = 0;
92
93         return state;
94 }
95
96 /**
97  * intel_plane_destroy_state - destroy plane state
98  * @plane: drm plane
99  * @state: state object to destroy
100  *
101  * Destroys the plane state (both common and Intel-specific) for the
102  * specified plane.
103  */
104 void
105 intel_plane_destroy_state(struct drm_plane *plane,
106                           struct drm_plane_state *state)
107 {
108         WARN_ON(to_intel_plane_state(state)->vma);
109
110         drm_atomic_helper_plane_destroy_state(plane, state);
111 }
112
113 int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
114                                         struct intel_crtc_state *crtc_state,
115                                         const struct intel_plane_state *old_plane_state,
116                                         struct intel_plane_state *intel_state)
117 {
118         struct drm_plane *plane = intel_state->base.plane;
119         struct drm_plane_state *state = &intel_state->base;
120         struct intel_plane *intel_plane = to_intel_plane(plane);
121         int ret;
122
123         crtc_state->active_planes &= ~BIT(intel_plane->id);
124         crtc_state->nv12_planes &= ~BIT(intel_plane->id);
125         intel_state->base.visible = false;
126
127         /* If this is a cursor plane, no further checks are needed. */
128         if (!intel_state->base.crtc && !old_plane_state->base.crtc)
129                 return 0;
130
131         ret = intel_plane->check_plane(crtc_state, intel_state);
132         if (ret)
133                 return ret;
134
135         /* FIXME pre-g4x don't work like this */
136         if (state->visible)
137                 crtc_state->active_planes |= BIT(intel_plane->id);
138
139         if (state->visible && state->fb->format->format == DRM_FORMAT_NV12)
140                 crtc_state->nv12_planes |= BIT(intel_plane->id);
141
142         return intel_plane_atomic_calc_changes(old_crtc_state,
143                                                &crtc_state->base,
144                                                old_plane_state,
145                                                state);
146 }
147
148 static int intel_plane_atomic_check(struct drm_plane *plane,
149                                     struct drm_plane_state *new_plane_state)
150 {
151         struct drm_atomic_state *state = new_plane_state->state;
152         const struct drm_plane_state *old_plane_state =
153                 drm_atomic_get_old_plane_state(state, plane);
154         struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc;
155         const struct drm_crtc_state *old_crtc_state;
156         struct drm_crtc_state *new_crtc_state;
157
158         new_plane_state->visible = false;
159         if (!crtc)
160                 return 0;
161
162         old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
163         new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
164
165         return intel_plane_atomic_check_with_state(to_intel_crtc_state(old_crtc_state),
166                                                    to_intel_crtc_state(new_crtc_state),
167                                                    to_intel_plane_state(old_plane_state),
168                                                    to_intel_plane_state(new_plane_state));
169 }
170
171 void intel_update_planes_on_crtc(struct intel_atomic_state *old_state,
172                                  struct intel_crtc *crtc,
173                                  struct intel_crtc_state *old_crtc_state,
174                                  struct intel_crtc_state *new_crtc_state)
175 {
176         struct intel_plane_state *new_plane_state;
177         struct intel_plane *plane;
178         u32 update_mask;
179         int i;
180
181         update_mask = old_crtc_state->active_planes;
182         update_mask |= new_crtc_state->active_planes;
183
184         for_each_new_intel_plane_in_state(old_state, plane, new_plane_state, i) {
185                 if (crtc->pipe != plane->pipe ||
186                     !(update_mask & BIT(plane->id)))
187                         continue;
188
189                 if (new_plane_state->base.visible) {
190                         trace_intel_update_plane(&plane->base, crtc);
191
192                         plane->update_plane(plane, new_crtc_state, new_plane_state);
193                 } else if (new_plane_state->slave) {
194                         struct intel_plane *master =
195                                 new_plane_state->linked_plane;
196
197                         /*
198                          * We update the slave plane from this function because
199                          * programming it from the master plane's update_plane
200                          * callback runs into issues when the Y plane is
201                          * reassigned, disabled or used by a different plane.
202                          *
203                          * The slave plane is updated with the master plane's
204                          * plane_state.
205                          */
206                         new_plane_state =
207                                 intel_atomic_get_new_plane_state(old_state, master);
208
209                         trace_intel_update_plane(&plane->base, crtc);
210
211                         plane->update_slave(plane, new_crtc_state, new_plane_state);
212                 } else {
213                         trace_intel_disable_plane(&plane->base, crtc);
214
215                         plane->disable_plane(plane, crtc);
216                 }
217         }
218 }
219
220 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
221         .prepare_fb = intel_prepare_plane_fb,
222         .cleanup_fb = intel_cleanup_plane_fb,
223         .atomic_check = intel_plane_atomic_check,
224 };
225
226 /**
227  * intel_plane_atomic_get_property - fetch plane property value
228  * @plane: plane to fetch property for
229  * @state: state containing the property value
230  * @property: property to look up
231  * @val: pointer to write property value into
232  *
233  * The DRM core does not store shadow copies of properties for
234  * atomic-capable drivers.  This entrypoint is used to fetch
235  * the current value of a driver-specific plane property.
236  */
237 int
238 intel_plane_atomic_get_property(struct drm_plane *plane,
239                                 const struct drm_plane_state *state,
240                                 struct drm_property *property,
241                                 uint64_t *val)
242 {
243         DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
244                       property->base.id, property->name);
245         return -EINVAL;
246 }
247
248 /**
249  * intel_plane_atomic_set_property - set plane property value
250  * @plane: plane to set property for
251  * @state: state to update property value in
252  * @property: property to set
253  * @val: value to set property to
254  *
255  * Writes the specified property value for a plane into the provided atomic
256  * state object.
257  *
258  * Returns 0 on success, -EINVAL on unrecognized properties
259  */
260 int
261 intel_plane_atomic_set_property(struct drm_plane *plane,
262                                 struct drm_plane_state *state,
263                                 struct drm_property *property,
264                                 uint64_t val)
265 {
266         DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
267                       property->base.id, property->name);
268         return -EINVAL;
269 }
This page took 0.047624 seconds and 4 git commands to generate.