aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-07-25 15:30:38 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-05 12:05:36 -0500
commitcc4ceb484b37b9369e0d4e8682b7ae1849ae4579 (patch)
treeefffd94cfe3fd6e81f7b22c9b0f3d181d4f2267b
parent144ecb97cd57d2a61cc455730a3337e413499cae (diff)
drm: Global atomic state handling
Some differences compared to Rob's patches again: - Dropped the committed and checked booleans. Checking will be internally enforced by always calling ->atomic_check before ->atomic_commit. And async handling needs to be solved differently because the current scheme completely side-steps ww mutex deadlock avoidance (and so either reinvents a new deadlock avoidance wheel or like the current code just deadlocks). - State for connectors needed to be added, since now they have a full-blown drm_connector_state (so that drivers have something to attach their own stuff to). - Refcounting is gone. I plane to solve async updates differently, since the lock-passing scheme doesn't cut it (since it abuses ww mutexes). Essentially what we need for async is a simple ownership transfer from the caller to the driver. That doesn't need full-blown refcounting. - The acquire ctx is a pointer. Real atomic callers should have that on their stack, legacy entry points need to put the right one (obtained by drm_modeset_legacy_acuire_ctx) in there. - I've dropped all hooks except check/commit. All the begin/end handling is done by core functions and is the same. - commit/check are just thin wrappers that ensure that ->check is always called. - To help out with locking in the legacy implementations I've added a helper to just grab all locks in the backoff case. v2: Add notices that check/commit can fail with EDEADLK. v3: - More consistent naming for state_alloc. - Add state_clear which is needed for backoff and retry. v4: Planes/connectors can switch between crtcs, and we need to be careful that we grab the state (and locks) for both the old and new crtc. Improve the interface functions to ensure this. v5: Add functions to grab affected connectors for a crtc and to recompute the crtc->enable state. This is useful for both helper and atomic ioctl code when e.g. removing a connector. v6: Squash in fixup from Fengguang to use ERR_CAST. v7: Add debug output. v8: Make checkpatch happy about kcalloc argument ordering. v9: Improve kerneldoc in drm_crtc.h v10: - Fix another kcalloc argument misorder I've missed. - More polish for kerneldoc. v11: Clarify the ownership rules for the state object. The new rule is that a successful drm_atomic_commit (whether synchronous or asnyc) always inherits the state and is responsible for the clean-up. That way async and sync ->commit functions are more similar. v12: A few bugfixes: - Assign state->state pointers correctly when grabbing state objects - we need to link them up with the global state. - Handle a NULL crtc in set_crtc_for_plane to simplify code flow a bit for the callers of this function. v13: Review from Sean: - kerneldoc spelling fixes - Don't overallocate states->planes. - Handle NULL crtc in set_crtc_for_connector. v14: Sprinkle __must_check over all functions which do wait/wound locking to make sure callers don't forget this. Since I have ;-) v15: Be more explicit in the kerneldoc when functions can return -EDEADLK what to do. And that every other -errno is fatal. v16: Indent with tabs instead of space, spotted by Ander. v17: Review from Thierry, small kerneldoc and other naming polish. Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Ander Conselvan de Oliveira <conselvan2@gmail.com> Cc: Daniel Thompson <daniel.thompson@linaro.org> Cc: Fengguang Wu <fengguang.wu@intel.com> Cc: Sean Paul <seanpaul@chromium.org> Cc: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--Documentation/DocBook/drm.tmpl4
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/drm_atomic.c600
-rw-r--r--include/drm/drm_atomic.h65
-rw-r--r--include/drm/drm_crtc.h50
5 files changed, 712 insertions, 9 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index f83d3b6ea4e5..748513b34025 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -996,6 +996,10 @@ int max_width, max_height;</synopsis>
996!Edrivers/gpu/drm/drm_modes.c 996!Edrivers/gpu/drm/drm_modes.c
997 </sect2> 997 </sect2>
998 <sect2> 998 <sect2>
999 <title>Atomic Mode Setting Function Reference</title>
1000!Edrivers/gpu/drm/drm_atomic.c
1001 </sect2>
1002 <sect2>
999 <title>Frame Buffer Creation</title> 1003 <title>Frame Buffer Creation</title>
1000 <synopsis>struct drm_framebuffer *(*fb_create)(struct drm_device *dev, 1004 <synopsis>struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
1001 struct drm_file *file_priv, 1005 struct drm_file *file_priv,
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 9292a761ea6d..c5e37dc459ee 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
14 drm_info.o drm_debugfs.o drm_encoder_slave.o \ 14 drm_info.o drm_debugfs.o drm_encoder_slave.o \
15 drm_trace_points.o drm_global.o drm_prime.o \ 15 drm_trace_points.o drm_global.o drm_prime.o \
16 drm_rect.o drm_vma_manager.o drm_flip_work.o \ 16 drm_rect.o drm_vma_manager.o drm_flip_work.o \
17 drm_modeset_lock.o 17 drm_modeset_lock.o drm_atomic.o
18 18
19drm-$(CONFIG_COMPAT) += drm_ioc32.o 19drm-$(CONFIG_COMPAT) += drm_ioc32.o
20drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o 20drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
new file mode 100644
index 000000000000..ad15a88c0f74
--- /dev/null
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -0,0 +1,600 @@
1/*
2 * Copyright (C) 2014 Red Hat
3 * Copyright (C) 2014 Intel Corp.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Rob Clark <robdclark@gmail.com>
25 * Daniel Vetter <daniel.vetter@ffwll.ch>
26 */
27
28
29#include <drm/drmP.h>
30#include <drm/drm_atomic.h>
31#include <drm/drm_plane_helper.h>
32
33static void kfree_state(struct drm_atomic_state *state)
34{
35 kfree(state->connectors);
36 kfree(state->connector_states);
37 kfree(state->crtcs);
38 kfree(state->crtc_states);
39 kfree(state->planes);
40 kfree(state->plane_states);
41 kfree(state);
42}
43
44/**
45 * drm_atomic_state_alloc - allocate atomic state
46 * @dev: DRM device
47 *
48 * This allocates an empty atomic state to track updates.
49 */
50struct drm_atomic_state *
51drm_atomic_state_alloc(struct drm_device *dev)
52{
53 struct drm_atomic_state *state;
54
55 state = kzalloc(sizeof(*state), GFP_KERNEL);
56 if (!state)
57 return NULL;
58
59 state->crtcs = kcalloc(dev->mode_config.num_crtc,
60 sizeof(*state->crtcs), GFP_KERNEL);
61 if (!state->crtcs)
62 goto fail;
63 state->crtc_states = kcalloc(dev->mode_config.num_crtc,
64 sizeof(*state->crtc_states), GFP_KERNEL);
65 if (!state->crtc_states)
66 goto fail;
67 state->planes = kcalloc(dev->mode_config.num_total_plane,
68 sizeof(*state->planes), GFP_KERNEL);
69 if (!state->planes)
70 goto fail;
71 state->plane_states = kcalloc(dev->mode_config.num_total_plane,
72 sizeof(*state->plane_states), GFP_KERNEL);
73 if (!state->plane_states)
74 goto fail;
75 state->connectors = kcalloc(dev->mode_config.num_connector,
76 sizeof(*state->connectors),
77 GFP_KERNEL);
78 if (!state->connectors)
79 goto fail;
80 state->connector_states = kcalloc(dev->mode_config.num_connector,
81 sizeof(*state->connector_states),
82 GFP_KERNEL);
83 if (!state->connector_states)
84 goto fail;
85
86 state->dev = dev;
87
88 DRM_DEBUG_KMS("Allocate atomic state %p\n", state);
89
90 return state;
91fail:
92 kfree_state(state);
93
94 return NULL;
95}
96EXPORT_SYMBOL(drm_atomic_state_alloc);
97
98/**
99 * drm_atomic_state_clear - clear state object
100 * @state: atomic state
101 *
102 * When the w/w mutex algorithm detects a deadlock we need to back off and drop
103 * all locks. So someone else could sneak in and change the current modeset
104 * configuration. Which means that all the state assembled in @state is no
105 * longer an atomic update to the current state, but to some arbitrary earlier
106 * state. Which could break assumptions the driver's ->atomic_check likely
107 * relies on.
108 *
109 * Hence we must clear all cached state and completely start over, using this
110 * function.
111 */
112void drm_atomic_state_clear(struct drm_atomic_state *state)
113{
114 struct drm_device *dev = state->dev;
115 int i;
116
117 DRM_DEBUG_KMS("Clearing atomic state %p\n", state);
118
119 for (i = 0; i < dev->mode_config.num_connector; i++) {
120 struct drm_connector *connector = state->connectors[i];
121
122 if (!connector)
123 continue;
124
125 connector->funcs->atomic_destroy_state(connector,
126 state->connector_states[i]);
127 }
128
129 for (i = 0; i < dev->mode_config.num_crtc; i++) {
130 struct drm_crtc *crtc = state->crtcs[i];
131
132 if (!crtc)
133 continue;
134
135 crtc->funcs->atomic_destroy_state(crtc,
136 state->crtc_states[i]);
137 }
138
139 for (i = 0; i < dev->mode_config.num_total_plane; i++) {
140 struct drm_plane *plane = state->planes[i];
141
142 if (!plane)
143 continue;
144
145 plane->funcs->atomic_destroy_state(plane,
146 state->plane_states[i]);
147 }
148}
149EXPORT_SYMBOL(drm_atomic_state_clear);
150
151/**
152 * drm_atomic_state_free - free all memory for an atomic state
153 * @state: atomic state to deallocate
154 *
155 * This frees all memory associated with an atomic state, including all the
156 * per-object state for planes, crtcs and connectors.
157 */
158void drm_atomic_state_free(struct drm_atomic_state *state)
159{
160 drm_atomic_state_clear(state);
161
162 DRM_DEBUG_KMS("Freeing atomic state %p\n", state);
163
164 kfree_state(state);
165}
166EXPORT_SYMBOL(drm_atomic_state_free);
167
168/**
169 * drm_atomic_get_crtc_state - get crtc state
170 * @state: global atomic state object
171 * @crtc: crtc to get state object for
172 *
173 * This function returns the crtc state for the given crtc, allocating it if
174 * needed. It will also grab the relevant crtc lock to make sure that the state
175 * is consistent.
176 *
177 * Returns:
178 *
179 * Either the allocated state or the error code encoded into the pointer. When
180 * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
181 * entire atomic sequence must be restarted. All other errors are fatal.
182 */
183struct drm_crtc_state *
184drm_atomic_get_crtc_state(struct drm_atomic_state *state,
185 struct drm_crtc *crtc)
186{
187 int ret, index;
188 struct drm_crtc_state *crtc_state;
189
190 index = drm_crtc_index(crtc);
191
192 if (state->crtc_states[index])
193 return state->crtc_states[index];
194
195 ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx);
196 if (ret)
197 return ERR_PTR(ret);
198
199 crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
200 if (!crtc_state)
201 return ERR_PTR(-ENOMEM);
202
203 state->crtc_states[index] = crtc_state;
204 state->crtcs[index] = crtc;
205 crtc_state->state = state;
206
207 DRM_DEBUG_KMS("Added [CRTC:%d] %p state to %p\n",
208 crtc->base.id, crtc_state, state);
209
210 return crtc_state;
211}
212EXPORT_SYMBOL(drm_atomic_get_crtc_state);
213
214/**
215 * drm_atomic_get_plane_state - get plane state
216 * @state: global atomic state object
217 * @plane: plane to get state object for
218 *
219 * This function returns the plane state for the given plane, allocating it if
220 * needed. It will also grab the relevant plane lock to make sure that the state
221 * is consistent.
222 *
223 * Returns:
224 *
225 * Either the allocated state or the error code encoded into the pointer. When
226 * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
227 * entire atomic sequence must be restarted. All other errors are fatal.
228 */
229struct drm_plane_state *
230drm_atomic_get_plane_state(struct drm_atomic_state *state,
231 struct drm_plane *plane)
232{
233 int ret, index;
234 struct drm_plane_state *plane_state;
235
236 index = drm_plane_index(plane);
237
238 if (state->plane_states[index])
239 return state->plane_states[index];
240
241 /*
242 * TODO: We currently don't have per-plane mutexes. So instead of trying
243 * crazy tricks with deferring plane->crtc and hoping for the best just
244 * grab all crtc locks. Once we have per-plane locks we must update this
245 * to only take the plane mutex.
246 */
247 ret = drm_modeset_lock_all_crtcs(state->dev, state->acquire_ctx);
248 if (ret)
249 return ERR_PTR(ret);
250
251 plane_state = plane->funcs->atomic_duplicate_state(plane);
252 if (!plane_state)
253 return ERR_PTR(-ENOMEM);
254
255 state->plane_states[index] = plane_state;
256 state->planes[index] = plane;
257 plane_state->state = state;
258
259 DRM_DEBUG_KMS("Added [PLANE:%d] %p state to %p\n",
260 plane->base.id, plane_state, state);
261
262 if (plane_state->crtc) {
263 struct drm_crtc_state *crtc_state;
264
265 crtc_state = drm_atomic_get_crtc_state(state,
266 plane_state->crtc);
267 if (IS_ERR(crtc_state))
268 return ERR_CAST(crtc_state);
269 }
270
271 return plane_state;
272}
273EXPORT_SYMBOL(drm_atomic_get_plane_state);
274
275/**
276 * drm_atomic_get_connector_state - get connector state
277 * @state: global atomic state object
278 * @connector: connector to get state object for
279 *
280 * This function returns the connector state for the given connector,
281 * allocating it if needed. It will also grab the relevant connector lock to
282 * make sure that the state is consistent.
283 *
284 * Returns:
285 *
286 * Either the allocated state or the error code encoded into the pointer. When
287 * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
288 * entire atomic sequence must be restarted. All other errors are fatal.
289 */
290struct drm_connector_state *
291drm_atomic_get_connector_state(struct drm_atomic_state *state,
292 struct drm_connector *connector)
293{
294 int ret, index;
295 struct drm_mode_config *config = &connector->dev->mode_config;
296 struct drm_connector_state *connector_state;
297
298 index = drm_connector_index(connector);
299
300 if (state->connector_states[index])
301 return state->connector_states[index];
302
303 ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
304 if (ret)
305 return ERR_PTR(ret);
306
307 connector_state = connector->funcs->atomic_duplicate_state(connector);
308 if (!connector_state)
309 return ERR_PTR(-ENOMEM);
310
311 state->connector_states[index] = connector_state;
312 state->connectors[index] = connector;
313 connector_state->state = state;
314
315 DRM_DEBUG_KMS("Added [CONNECTOR:%d] %p state to %p\n",
316 connector->base.id, connector_state, state);
317
318 if (connector_state->crtc) {
319 struct drm_crtc_state *crtc_state;
320
321 crtc_state = drm_atomic_get_crtc_state(state,
322 connector_state->crtc);
323 if (IS_ERR(crtc_state))
324 return ERR_CAST(crtc_state);
325 }
326
327 return connector_state;
328}
329EXPORT_SYMBOL(drm_atomic_get_connector_state);
330
331/**
332 * drm_atomic_set_crtc_for_plane - set crtc for plane
333 * @plane_state: atomic state object for the plane
334 * @crtc: crtc to use for the plane
335 *
336 * Changing the assigned crtc for a plane requires us to grab the lock and state
337 * for the new crtc, as needed. This function takes care of all these details
338 * besides updating the pointer in the state object itself.
339 *
340 * Returns:
341 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
342 * then the w/w mutex code has detected a deadlock and the entire atomic
343 * sequence must be restarted. All other errors are fatal.
344 */
345int
346drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
347 struct drm_crtc *crtc)
348{
349 struct drm_crtc_state *crtc_state;
350
351 if (crtc) {
352 crtc_state = drm_atomic_get_crtc_state(plane_state->state,
353 crtc);
354 if (IS_ERR(crtc_state))
355 return PTR_ERR(crtc_state);
356 }
357
358 plane_state->crtc = crtc;
359
360 if (crtc)
361 DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n",
362 plane_state, crtc->base.id);
363 else
364 DRM_DEBUG_KMS("Link plane state %p to [NOCRTC]\n", plane_state);
365
366 return 0;
367}
368EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
369
370/**
371 * drm_atomic_set_crtc_for_connector - set crtc for connector
372 * @conn_state: atomic state object for the connector
373 * @crtc: crtc to use for the connector
374 *
375 * Changing the assigned crtc for a connector requires us to grab the lock and
376 * state for the new crtc, as needed. This function takes care of all these
377 * details besides updating the pointer in the state object itself.
378 *
379 * Returns:
380 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
381 * then the w/w mutex code has detected a deadlock and the entire atomic
382 * sequence must be restarted. All other errors are fatal.
383 */
384int
385drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
386 struct drm_crtc *crtc)
387{
388 struct drm_crtc_state *crtc_state;
389
390 if (crtc) {
391 crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
392 if (IS_ERR(crtc_state))
393 return PTR_ERR(crtc_state);
394 }
395
396 conn_state->crtc = crtc;
397
398 if (crtc)
399 DRM_DEBUG_KMS("Link connector state %p to [CRTC:%d]\n",
400 conn_state, crtc->base.id);
401 else
402 DRM_DEBUG_KMS("Link connector state %p to [NOCRTC]\n",
403 conn_state);
404
405 return 0;
406}
407EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
408
409/**
410 * drm_atomic_add_affected_connectors - add connectors for crtc
411 * @state: atomic state
412 * @crtc: DRM crtc
413 *
414 * This function walks the current configuration and adds all connectors
415 * currently using @crtc to the atomic configuration @state. Note that this
416 * function must acquire the connection mutex. This can potentially cause
417 * unneeded seralization if the update is just for the planes on one crtc. Hence
418 * drivers and helpers should only call this when really needed (e.g. when a
419 * full modeset needs to happen due to some change).
420 *
421 * Returns:
422 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
423 * then the w/w mutex code has detected a deadlock and the entire atomic
424 * sequence must be restarted. All other errors are fatal.
425 */
426int
427drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
428 struct drm_crtc *crtc)
429{
430 struct drm_mode_config *config = &state->dev->mode_config;
431 struct drm_connector *connector;
432 struct drm_connector_state *conn_state;
433 int ret;
434
435 ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
436 if (ret)
437 return ret;
438
439 DRM_DEBUG_KMS("Adding all current connectors for [CRTC:%d] to %p\n",
440 crtc->base.id, state);
441
442 /*
443 * Changed connectors are already in @state, so only need to look at the
444 * current configuration.
445 */
446 list_for_each_entry(connector, &config->connector_list, head) {
447 if (connector->state->crtc != crtc)
448 continue;
449
450 conn_state = drm_atomic_get_connector_state(state, connector);
451 if (IS_ERR(conn_state))
452 return PTR_ERR(conn_state);
453 }
454
455 return 0;
456}
457EXPORT_SYMBOL(drm_atomic_add_affected_connectors);
458
459/**
460 * drm_atomic_connectors_for_crtc - count number of connected outputs
461 * @state: atomic state
462 * @crtc: DRM crtc
463 *
464 * This function counts all connectors which will be connected to @crtc
465 * according to @state. Useful to recompute the enable state for @crtc.
466 */
467int
468drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
469 struct drm_crtc *crtc)
470{
471 int nconnectors = state->dev->mode_config.num_connector;
472 int i, num_connected_connectors = 0;
473
474 for (i = 0; i < nconnectors; i++) {
475 struct drm_connector_state *conn_state;
476
477 conn_state = state->connector_states[i];
478
479 if (conn_state && conn_state->crtc == crtc)
480 num_connected_connectors++;
481 }
482
483 DRM_DEBUG_KMS("State %p has %i connectors for [CRTC:%d]\n",
484 state, num_connected_connectors, crtc->base.id);
485
486 return num_connected_connectors;
487}
488EXPORT_SYMBOL(drm_atomic_connectors_for_crtc);
489
490/**
491 * drm_atomic_legacy_backoff - locking backoff for legacy ioctls
492 * @state: atomic state
493 *
494 * This function should be used by legacy entry points which don't understand
495 * -EDEADLK semantics. For simplicity this one will grab all modeset locks after
496 * the slowpath completed.
497 */
498void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
499{
500 int ret;
501
502retry:
503 drm_modeset_backoff(state->acquire_ctx);
504
505 ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
506 state->acquire_ctx);
507 if (ret)
508 goto retry;
509 ret = drm_modeset_lock_all_crtcs(state->dev,
510 state->acquire_ctx);
511 if (ret)
512 goto retry;
513}
514EXPORT_SYMBOL(drm_atomic_legacy_backoff);
515
516/**
517 * drm_atomic_check_only - check whether a given config would work
518 * @state: atomic configuration to check
519 *
520 * Note that this function can return -EDEADLK if the driver needed to acquire
521 * more locks but encountered a deadlock. The caller must then do the usual w/w
522 * backoff dance and restart. All other errors are fatal.
523 *
524 * Returns:
525 * 0 on success, negative error code on failure.
526 */
527int drm_atomic_check_only(struct drm_atomic_state *state)
528{
529 struct drm_mode_config *config = &state->dev->mode_config;
530
531 DRM_DEBUG_KMS("checking %p\n", state);
532
533 if (config->funcs->atomic_check)
534 return config->funcs->atomic_check(state->dev, state);
535 else
536 return 0;
537}
538EXPORT_SYMBOL(drm_atomic_check_only);
539
540/**
541 * drm_atomic_commit - commit configuration atomically
542 * @state: atomic configuration to check
543 *
544 * Note that this function can return -EDEADLK if the driver needed to acquire
545 * more locks but encountered a deadlock. The caller must then do the usual w/w
546 * backoff dance and restart. All other errors are fatal.
547 *
548 * Also note that on successful execution ownership of @state is transferred
549 * from the caller of this function to the function itself. The caller must not
550 * free or in any other way access @state. If the function fails then the caller
551 * must clean up @state itself.
552 *
553 * Returns:
554 * 0 on success, negative error code on failure.
555 */
556int drm_atomic_commit(struct drm_atomic_state *state)
557{
558 struct drm_mode_config *config = &state->dev->mode_config;
559 int ret;
560
561 ret = drm_atomic_check_only(state);
562 if (ret)
563 return ret;
564
565 DRM_DEBUG_KMS("commiting %p\n", state);
566
567 return config->funcs->atomic_commit(state->dev, state, false);
568}
569EXPORT_SYMBOL(drm_atomic_commit);
570
571/**
572 * drm_atomic_async_commit - atomic&async configuration commit
573 * @state: atomic configuration to check
574 *
575 * Note that this function can return -EDEADLK if the driver needed to acquire
576 * more locks but encountered a deadlock. The caller must then do the usual w/w
577 * backoff dance and restart. All other errors are fatal.
578 *
579 * Also note that on successful execution ownership of @state is transferred
580 * from the caller of this function to the function itself. The caller must not
581 * free or in any other way access @state. If the function fails then the caller
582 * must clean up @state itself.
583 *
584 * Returns:
585 * 0 on success, negative error code on failure.
586 */
587int drm_atomic_async_commit(struct drm_atomic_state *state)
588{
589 struct drm_mode_config *config = &state->dev->mode_config;
590 int ret;
591
592 ret = drm_atomic_check_only(state);
593 if (ret)
594 return ret;
595
596 DRM_DEBUG_KMS("commiting %p asynchronously\n", state);
597
598 return config->funcs->atomic_commit(state->dev, state, true);
599}
600EXPORT_SYMBOL(drm_atomic_async_commit);
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
new file mode 100644
index 000000000000..5bb15f550c42
--- /dev/null
+++ b/include/drm/drm_atomic.h
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2014 Red Hat
3 * Copyright (C) 2014 Intel Corp.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Rob Clark <robdclark@gmail.com>
25 * Daniel Vetter <daniel.vetter@ffwll.ch>
26 */
27
28#ifndef DRM_ATOMIC_H_
29#define DRM_ATOMIC_H_
30
31struct drm_atomic_state * __must_check
32drm_atomic_state_alloc(struct drm_device *dev);
33void drm_atomic_state_clear(struct drm_atomic_state *state);
34void drm_atomic_state_free(struct drm_atomic_state *state);
35
36struct drm_crtc_state * __must_check
37drm_atomic_get_crtc_state(struct drm_atomic_state *state,
38 struct drm_crtc *crtc);
39struct drm_plane_state * __must_check
40drm_atomic_get_plane_state(struct drm_atomic_state *state,
41 struct drm_plane *plane);
42struct drm_connector_state * __must_check
43drm_atomic_get_connector_state(struct drm_atomic_state *state,
44 struct drm_connector *connector);
45
46int __must_check
47drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
48 struct drm_crtc *crtc);
49int __must_check
50drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
51 struct drm_crtc *crtc);
52int __must_check
53drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
54 struct drm_crtc *crtc);
55int
56drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
57 struct drm_crtc *crtc);
58
59void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
60
61int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
62int __must_check drm_atomic_commit(struct drm_atomic_state *state);
63int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
64
65#endif /* DRM_ATOMIC_H_ */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3554868dbf09..c7a3400173a8 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -227,7 +227,7 @@ struct drm_bridge;
227struct drm_atomic_state; 227struct drm_atomic_state;
228 228
229/** 229/**
230 * struct drm_crtc_state - mutable crtc state 230 * struct drm_crtc_state - mutable CRTC state
231 * @enable: whether the CRTC should be enabled, gates all other state 231 * @enable: whether the CRTC should be enabled, gates all other state
232 * @mode: current mode timings 232 * @mode: current mode timings
233 * @event: optional pointer to a DRM event to signal upon completion of the 233 * @event: optional pointer to a DRM event to signal upon completion of the
@@ -235,7 +235,7 @@ struct drm_atomic_state;
235 * @state: backpointer to global drm_atomic_state 235 * @state: backpointer to global drm_atomic_state
236 */ 236 */
237struct drm_crtc_state { 237struct drm_crtc_state {
238 bool enable : 1; 238 bool enable;
239 239
240 struct drm_display_mode mode; 240 struct drm_display_mode mode;
241 241
@@ -314,7 +314,7 @@ struct drm_crtc_funcs {
314 /* atomic update handling */ 314 /* atomic update handling */
315 struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc); 315 struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
316 void (*atomic_destroy_state)(struct drm_crtc *crtc, 316 void (*atomic_destroy_state)(struct drm_crtc *crtc,
317 struct drm_crtc_state *cstate); 317 struct drm_crtc_state *state);
318 int (*atomic_set_property)(struct drm_crtc *crtc, 318 int (*atomic_set_property)(struct drm_crtc *crtc,
319 struct drm_crtc_state *state, 319 struct drm_crtc_state *state,
320 struct drm_property *property, 320 struct drm_property *property,
@@ -417,7 +417,7 @@ struct drm_crtc {
417 417
418/** 418/**
419 * struct drm_connector_state - mutable connector state 419 * struct drm_connector_state - mutable connector state
420 * @crtc: crtc to connect connector to, NULL if disabled 420 * @crtc: CRTC to connect connector to, NULL if disabled
421 * @state: backpointer to global drm_atomic_state 421 * @state: backpointer to global drm_atomic_state
422 */ 422 */
423struct drm_connector_state { 423struct drm_connector_state {
@@ -441,7 +441,6 @@ struct drm_connector_state {
441 * @atomic_destroy_state: destroy an atomic state for this connector 441 * @atomic_destroy_state: destroy an atomic state for this connector
442 * @atomic_set_property: set a property on an atomic state for this connector 442 * @atomic_set_property: set a property on an atomic state for this connector
443 * 443 *
444 *
445 * Each CRTC may have one or more connectors attached to it. The functions 444 * Each CRTC may have one or more connectors attached to it. The functions
446 * below allow the core DRM code to control connectors, enumerate available modes, 445 * below allow the core DRM code to control connectors, enumerate available modes,
447 * etc. 446 * etc.
@@ -469,7 +468,7 @@ struct drm_connector_funcs {
469 /* atomic update handling */ 468 /* atomic update handling */
470 struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector); 469 struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
471 void (*atomic_destroy_state)(struct drm_connector *connector, 470 void (*atomic_destroy_state)(struct drm_connector *connector,
472 struct drm_connector_state *cstate); 471 struct drm_connector_state *state);
473 int (*atomic_set_property)(struct drm_connector *connector, 472 int (*atomic_set_property)(struct drm_connector *connector,
474 struct drm_connector_state *state, 473 struct drm_connector_state *state,
475 struct drm_property *property, 474 struct drm_property *property,
@@ -640,7 +639,7 @@ struct drm_connector {
640/** 639/**
641 * struct drm_plane_state - mutable plane state 640 * struct drm_plane_state - mutable plane state
642 * @crtc: currently bound CRTC, NULL if disabled 641 * @crtc: currently bound CRTC, NULL if disabled
643 * @fb: currently bound fb 642 * @fb: currently bound framebuffer
644 * @crtc_x: left position of visible portion of plane on crtc 643 * @crtc_x: left position of visible portion of plane on crtc
645 * @crtc_y: upper position of visible portion of plane on crtc 644 * @crtc_y: upper position of visible portion of plane on crtc
646 * @crtc_w: width of visible portion of plane on crtc 645 * @crtc_w: width of visible portion of plane on crtc
@@ -697,7 +696,7 @@ struct drm_plane_funcs {
697 /* atomic update handling */ 696 /* atomic update handling */
698 struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane); 697 struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);
699 void (*atomic_destroy_state)(struct drm_plane *plane, 698 void (*atomic_destroy_state)(struct drm_plane *plane,
700 struct drm_plane_state *cstate); 699 struct drm_plane_state *state);
701 int (*atomic_set_property)(struct drm_plane *plane, 700 int (*atomic_set_property)(struct drm_plane *plane,
702 struct drm_plane_state *state, 701 struct drm_plane_state *state,
703 struct drm_property *property, 702 struct drm_property *property,
@@ -794,6 +793,32 @@ struct drm_bridge {
794}; 793};
795 794
796/** 795/**
796 * struct struct drm_atomic_state - the global state object for atomic updates
797 * @dev: parent DRM device
798 * @flags: state flags like async update
799 * @planes: pointer to array of plane pointers
800 * @plane_states: pointer to array of plane states pointers
801 * @crtcs: pointer to array of CRTC pointers
802 * @crtc_states: pointer to array of CRTC states pointers
803 * @connectors: pointer to array of connector pointers
804 * @connector_states: pointer to array of connector states pointers
805 * @acquire_ctx: acquire context for this atomic modeset state update
806 */
807struct drm_atomic_state {
808 struct drm_device *dev;
809 uint32_t flags;
810 struct drm_plane **planes;
811 struct drm_plane_state **plane_states;
812 struct drm_crtc **crtcs;
813 struct drm_crtc_state **crtc_states;
814 struct drm_connector **connectors;
815 struct drm_connector_state **connector_states;
816
817 struct drm_modeset_acquire_ctx *acquire_ctx;
818};
819
820
821/**
797 * struct drm_mode_set - new values for a CRTC config change 822 * struct drm_mode_set - new values for a CRTC config change
798 * @fb: framebuffer to use for new config 823 * @fb: framebuffer to use for new config
799 * @crtc: CRTC whose configuration we're about to change 824 * @crtc: CRTC whose configuration we're about to change
@@ -824,6 +849,9 @@ struct drm_mode_set {
824 * struct drm_mode_config_funcs - basic driver provided mode setting functions 849 * struct drm_mode_config_funcs - basic driver provided mode setting functions
825 * @fb_create: create a new framebuffer object 850 * @fb_create: create a new framebuffer object
826 * @output_poll_changed: function to handle output configuration changes 851 * @output_poll_changed: function to handle output configuration changes
852 * @atomic_check: check whether a give atomic state update is possible
853 * @atomic_commit: commit an atomic state update previously verified with
854 * atomic_check()
827 * 855 *
828 * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that 856 * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
829 * involve drivers. 857 * involve drivers.
@@ -833,6 +861,12 @@ struct drm_mode_config_funcs {
833 struct drm_file *file_priv, 861 struct drm_file *file_priv,
834 struct drm_mode_fb_cmd2 *mode_cmd); 862 struct drm_mode_fb_cmd2 *mode_cmd);
835 void (*output_poll_changed)(struct drm_device *dev); 863 void (*output_poll_changed)(struct drm_device *dev);
864
865 int (*atomic_check)(struct drm_device *dev,
866 struct drm_atomic_state *a);
867 int (*atomic_commit)(struct drm_device *dev,
868 struct drm_atomic_state *a,
869 bool async);
836}; 870};
837 871
838/** 872/**