Line data Source code
1 : /*
2 : * Copyright (C) 2018 Intel Corp.
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 shall be included in
12 : * all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 : * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 : * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 : * OTHER DEALINGS IN THE SOFTWARE.
21 : *
22 : * Authors:
23 : * Rob Clark <robdclark@gmail.com>
24 : * Daniel Vetter <daniel.vetter@ffwll.ch>
25 : */
26 :
27 : #include <drm/drm_atomic.h>
28 : #include <drm/drm_atomic_state_helper.h>
29 : #include <drm/drm_bridge.h>
30 : #include <drm/drm_connector.h>
31 : #include <drm/drm_crtc.h>
32 : #include <drm/drm_device.h>
33 : #include <drm/drm_plane.h>
34 : #include <drm/drm_print.h>
35 : #include <drm/drm_vblank.h>
36 : #include <drm/drm_writeback.h>
37 :
38 : #include <linux/slab.h>
39 : #include <linux/dma-fence.h>
40 :
41 : /**
42 : * DOC: atomic state reset and initialization
43 : *
44 : * Both the drm core and the atomic helpers assume that there is always the full
45 : * and correct atomic software state for all connectors, CRTCs and planes
46 : * available. Which is a bit a problem on driver load and also after system
47 : * suspend. One way to solve this is to have a hardware state read-out
48 : * infrastructure which reconstructs the full software state (e.g. the i915
49 : * driver).
50 : *
51 : * The simpler solution is to just reset the software state to everything off,
52 : * which is easiest to do by calling drm_mode_config_reset(). To facilitate this
53 : * the atomic helpers provide default reset implementations for all hooks.
54 : *
55 : * On the upside the precise state tracking of atomic simplifies system suspend
56 : * and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
57 : * is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
58 : * For other drivers the building blocks are split out, see the documentation
59 : * for these functions.
60 : */
61 :
62 : /**
63 : * __drm_atomic_helper_crtc_state_reset - reset the CRTC state
64 : * @crtc_state: atomic CRTC state, must not be NULL
65 : * @crtc: CRTC object, must not be NULL
66 : *
67 : * Initializes the newly allocated @crtc_state with default
68 : * values. This is useful for drivers that subclass the CRTC state.
69 : */
70 : void
71 0 : __drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state,
72 : struct drm_crtc *crtc)
73 : {
74 0 : crtc_state->crtc = crtc;
75 0 : }
76 : EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset);
77 :
78 : /**
79 : * __drm_atomic_helper_crtc_reset - reset state on CRTC
80 : * @crtc: drm CRTC
81 : * @crtc_state: CRTC state to assign
82 : *
83 : * Initializes the newly allocated @crtc_state and assigns it to
84 : * the &drm_crtc->state pointer of @crtc, usually required when
85 : * initializing the drivers or when called from the &drm_crtc_funcs.reset
86 : * hook.
87 : *
88 : * This is useful for drivers that subclass the CRTC state.
89 : */
90 : void
91 0 : __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
92 : struct drm_crtc_state *crtc_state)
93 : {
94 0 : if (crtc_state)
95 : __drm_atomic_helper_crtc_state_reset(crtc_state, crtc);
96 :
97 0 : if (drm_dev_has_vblank(crtc->dev))
98 0 : drm_crtc_vblank_reset(crtc);
99 :
100 0 : crtc->state = crtc_state;
101 0 : }
102 : EXPORT_SYMBOL(__drm_atomic_helper_crtc_reset);
103 :
104 : /**
105 : * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
106 : * @crtc: drm CRTC
107 : *
108 : * Resets the atomic state for @crtc by freeing the state pointer (which might
109 : * be NULL, e.g. at driver load time) and allocating a new empty state object.
110 : */
111 0 : void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
112 : {
113 0 : struct drm_crtc_state *crtc_state =
114 : kzalloc(sizeof(*crtc->state), GFP_KERNEL);
115 :
116 0 : if (crtc->state)
117 0 : crtc->funcs->atomic_destroy_state(crtc, crtc->state);
118 :
119 0 : __drm_atomic_helper_crtc_reset(crtc, crtc_state);
120 0 : }
121 : EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
122 :
123 : /**
124 : * __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
125 : * @crtc: CRTC object
126 : * @state: atomic CRTC state
127 : *
128 : * Copies atomic state from a CRTC's current state and resets inferred values.
129 : * This is useful for drivers that subclass the CRTC state.
130 : */
131 0 : void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
132 : struct drm_crtc_state *state)
133 : {
134 0 : memcpy(state, crtc->state, sizeof(*state));
135 :
136 0 : if (state->mode_blob)
137 0 : drm_property_blob_get(state->mode_blob);
138 0 : if (state->degamma_lut)
139 0 : drm_property_blob_get(state->degamma_lut);
140 0 : if (state->ctm)
141 0 : drm_property_blob_get(state->ctm);
142 0 : if (state->gamma_lut)
143 0 : drm_property_blob_get(state->gamma_lut);
144 0 : state->mode_changed = false;
145 0 : state->active_changed = false;
146 0 : state->planes_changed = false;
147 0 : state->connectors_changed = false;
148 0 : state->color_mgmt_changed = false;
149 0 : state->zpos_changed = false;
150 0 : state->commit = NULL;
151 0 : state->event = NULL;
152 0 : state->async_flip = false;
153 :
154 : /* Self refresh should be canceled when a new update is available */
155 0 : state->active = drm_atomic_crtc_effectively_active(state);
156 0 : state->self_refresh_active = false;
157 0 : }
158 : EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
159 :
160 : /**
161 : * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
162 : * @crtc: drm CRTC
163 : *
164 : * Default CRTC state duplicate hook for drivers which don't have their own
165 : * subclassed CRTC state structure.
166 : */
167 : struct drm_crtc_state *
168 0 : drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
169 : {
170 : struct drm_crtc_state *state;
171 :
172 0 : if (WARN_ON(!crtc->state))
173 : return NULL;
174 :
175 0 : state = kmalloc(sizeof(*state), GFP_KERNEL);
176 0 : if (state)
177 0 : __drm_atomic_helper_crtc_duplicate_state(crtc, state);
178 :
179 : return state;
180 : }
181 : EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
182 :
183 : /**
184 : * __drm_atomic_helper_crtc_destroy_state - release CRTC state
185 : * @state: CRTC state object to release
186 : *
187 : * Releases all resources stored in the CRTC state without actually freeing
188 : * the memory of the CRTC state. This is useful for drivers that subclass the
189 : * CRTC state.
190 : */
191 0 : void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
192 : {
193 0 : if (state->commit) {
194 : /*
195 : * In the event that a non-blocking commit returns
196 : * -ERESTARTSYS before the commit_tail work is queued, we will
197 : * have an extra reference to the commit object. Release it, if
198 : * the event has not been consumed by the worker.
199 : *
200 : * state->event may be freed, so we can't directly look at
201 : * state->event->base.completion.
202 : */
203 0 : if (state->event && state->commit->abort_completion)
204 0 : drm_crtc_commit_put(state->commit);
205 :
206 0 : kfree(state->commit->event);
207 0 : state->commit->event = NULL;
208 :
209 0 : drm_crtc_commit_put(state->commit);
210 : }
211 :
212 0 : drm_property_blob_put(state->mode_blob);
213 0 : drm_property_blob_put(state->degamma_lut);
214 0 : drm_property_blob_put(state->ctm);
215 0 : drm_property_blob_put(state->gamma_lut);
216 0 : }
217 : EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
218 :
219 : /**
220 : * drm_atomic_helper_crtc_destroy_state - default state destroy hook
221 : * @crtc: drm CRTC
222 : * @state: CRTC state object to release
223 : *
224 : * Default CRTC state destroy hook for drivers which don't have their own
225 : * subclassed CRTC state structure.
226 : */
227 0 : void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
228 : struct drm_crtc_state *state)
229 : {
230 0 : __drm_atomic_helper_crtc_destroy_state(state);
231 0 : kfree(state);
232 0 : }
233 : EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
234 :
235 : /**
236 : * __drm_atomic_helper_plane_state_reset - resets plane state to default values
237 : * @plane_state: atomic plane state, must not be NULL
238 : * @plane: plane object, must not be NULL
239 : *
240 : * Initializes the newly allocated @plane_state with default
241 : * values. This is useful for drivers that subclass the CRTC state.
242 : */
243 0 : void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state,
244 : struct drm_plane *plane)
245 : {
246 : u64 val;
247 :
248 0 : plane_state->plane = plane;
249 0 : plane_state->rotation = DRM_MODE_ROTATE_0;
250 :
251 0 : plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE;
252 0 : plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
253 :
254 0 : if (plane->color_encoding_property) {
255 0 : if (!drm_object_property_get_default_value(&plane->base,
256 : plane->color_encoding_property,
257 : &val))
258 0 : plane_state->color_encoding = val;
259 : }
260 :
261 0 : if (plane->color_range_property) {
262 0 : if (!drm_object_property_get_default_value(&plane->base,
263 : plane->color_range_property,
264 : &val))
265 0 : plane_state->color_range = val;
266 : }
267 :
268 0 : if (plane->zpos_property) {
269 0 : if (!drm_object_property_get_default_value(&plane->base,
270 : plane->zpos_property,
271 : &val)) {
272 0 : plane_state->zpos = val;
273 0 : plane_state->normalized_zpos = val;
274 : }
275 : }
276 0 : }
277 : EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset);
278 :
279 : /**
280 : * __drm_atomic_helper_plane_reset - reset state on plane
281 : * @plane: drm plane
282 : * @plane_state: plane state to assign
283 : *
284 : * Initializes the newly allocated @plane_state and assigns it to
285 : * the &drm_crtc->state pointer of @plane, usually required when
286 : * initializing the drivers or when called from the &drm_plane_funcs.reset
287 : * hook.
288 : *
289 : * This is useful for drivers that subclass the plane state.
290 : */
291 0 : void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
292 : struct drm_plane_state *plane_state)
293 : {
294 0 : if (plane_state)
295 0 : __drm_atomic_helper_plane_state_reset(plane_state, plane);
296 :
297 0 : plane->state = plane_state;
298 0 : }
299 : EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
300 :
301 : /**
302 : * drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
303 : * @plane: drm plane
304 : *
305 : * Resets the atomic state for @plane by freeing the state pointer (which might
306 : * be NULL, e.g. at driver load time) and allocating a new empty state object.
307 : */
308 0 : void drm_atomic_helper_plane_reset(struct drm_plane *plane)
309 : {
310 0 : if (plane->state)
311 0 : __drm_atomic_helper_plane_destroy_state(plane->state);
312 :
313 0 : kfree(plane->state);
314 0 : plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
315 0 : if (plane->state)
316 0 : __drm_atomic_helper_plane_reset(plane, plane->state);
317 0 : }
318 : EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
319 :
320 : /**
321 : * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
322 : * @plane: plane object
323 : * @state: atomic plane state
324 : *
325 : * Copies atomic state from a plane's current state. This is useful for
326 : * drivers that subclass the plane state.
327 : */
328 0 : void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
329 : struct drm_plane_state *state)
330 : {
331 0 : memcpy(state, plane->state, sizeof(*state));
332 :
333 0 : if (state->fb)
334 0 : drm_framebuffer_get(state->fb);
335 :
336 0 : state->fence = NULL;
337 0 : state->commit = NULL;
338 0 : state->fb_damage_clips = NULL;
339 0 : }
340 : EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
341 :
342 : /**
343 : * drm_atomic_helper_plane_duplicate_state - default state duplicate hook
344 : * @plane: drm plane
345 : *
346 : * Default plane state duplicate hook for drivers which don't have their own
347 : * subclassed plane state structure.
348 : */
349 : struct drm_plane_state *
350 0 : drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
351 : {
352 : struct drm_plane_state *state;
353 :
354 0 : if (WARN_ON(!plane->state))
355 : return NULL;
356 :
357 0 : state = kmalloc(sizeof(*state), GFP_KERNEL);
358 0 : if (state)
359 0 : __drm_atomic_helper_plane_duplicate_state(plane, state);
360 :
361 : return state;
362 : }
363 : EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
364 :
365 : /**
366 : * __drm_atomic_helper_plane_destroy_state - release plane state
367 : * @state: plane state object to release
368 : *
369 : * Releases all resources stored in the plane state without actually freeing
370 : * the memory of the plane state. This is useful for drivers that subclass the
371 : * plane state.
372 : */
373 0 : void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
374 : {
375 0 : if (state->fb)
376 0 : drm_framebuffer_put(state->fb);
377 :
378 0 : if (state->fence)
379 0 : dma_fence_put(state->fence);
380 :
381 0 : if (state->commit)
382 0 : drm_crtc_commit_put(state->commit);
383 :
384 0 : drm_property_blob_put(state->fb_damage_clips);
385 0 : }
386 : EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
387 :
388 : /**
389 : * drm_atomic_helper_plane_destroy_state - default state destroy hook
390 : * @plane: drm plane
391 : * @state: plane state object to release
392 : *
393 : * Default plane state destroy hook for drivers which don't have their own
394 : * subclassed plane state structure.
395 : */
396 0 : void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
397 : struct drm_plane_state *state)
398 : {
399 0 : __drm_atomic_helper_plane_destroy_state(state);
400 0 : kfree(state);
401 0 : }
402 : EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
403 :
404 : /**
405 : * __drm_atomic_helper_connector_state_reset - reset the connector state
406 : * @conn_state: atomic connector state, must not be NULL
407 : * @connector: connectotr object, must not be NULL
408 : *
409 : * Initializes the newly allocated @conn_state with default
410 : * values. This is useful for drivers that subclass the connector state.
411 : */
412 : void
413 0 : __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state,
414 : struct drm_connector *connector)
415 : {
416 0 : conn_state->connector = connector;
417 0 : }
418 : EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset);
419 :
420 : /**
421 : * __drm_atomic_helper_connector_reset - reset state on connector
422 : * @connector: drm connector
423 : * @conn_state: connector state to assign
424 : *
425 : * Initializes the newly allocated @conn_state and assigns it to
426 : * the &drm_connector->state pointer of @connector, usually required when
427 : * initializing the drivers or when called from the &drm_connector_funcs.reset
428 : * hook.
429 : *
430 : * This is useful for drivers that subclass the connector state.
431 : */
432 : void
433 0 : __drm_atomic_helper_connector_reset(struct drm_connector *connector,
434 : struct drm_connector_state *conn_state)
435 : {
436 0 : if (conn_state)
437 : __drm_atomic_helper_connector_state_reset(conn_state, connector);
438 :
439 0 : connector->state = conn_state;
440 0 : }
441 : EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
442 :
443 : /**
444 : * drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
445 : * @connector: drm connector
446 : *
447 : * Resets the atomic state for @connector by freeing the state pointer (which
448 : * might be NULL, e.g. at driver load time) and allocating a new empty state
449 : * object.
450 : */
451 0 : void drm_atomic_helper_connector_reset(struct drm_connector *connector)
452 : {
453 0 : struct drm_connector_state *conn_state =
454 : kzalloc(sizeof(*conn_state), GFP_KERNEL);
455 :
456 0 : if (connector->state)
457 0 : __drm_atomic_helper_connector_destroy_state(connector->state);
458 :
459 0 : kfree(connector->state);
460 0 : __drm_atomic_helper_connector_reset(connector, conn_state);
461 0 : }
462 : EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
463 :
464 : /**
465 : * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
466 : * @connector: DRM connector
467 : *
468 : * Resets the TV-related properties attached to a connector.
469 : */
470 0 : void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
471 : {
472 0 : struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
473 0 : struct drm_connector_state *state = connector->state;
474 :
475 0 : state->tv.margins.left = cmdline->tv_margins.left;
476 0 : state->tv.margins.right = cmdline->tv_margins.right;
477 0 : state->tv.margins.top = cmdline->tv_margins.top;
478 0 : state->tv.margins.bottom = cmdline->tv_margins.bottom;
479 0 : }
480 : EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
481 :
482 : /**
483 : * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
484 : * @connector: connector object
485 : * @state: atomic connector state
486 : *
487 : * Copies atomic state from a connector's current state. This is useful for
488 : * drivers that subclass the connector state.
489 : */
490 : void
491 0 : __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
492 : struct drm_connector_state *state)
493 : {
494 0 : memcpy(state, connector->state, sizeof(*state));
495 0 : if (state->crtc)
496 : drm_connector_get(connector);
497 0 : state->commit = NULL;
498 :
499 0 : if (state->hdr_output_metadata)
500 0 : drm_property_blob_get(state->hdr_output_metadata);
501 :
502 : /* Don't copy over a writeback job, they are used only once */
503 0 : state->writeback_job = NULL;
504 0 : }
505 : EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
506 :
507 : /**
508 : * drm_atomic_helper_connector_duplicate_state - default state duplicate hook
509 : * @connector: drm connector
510 : *
511 : * Default connector state duplicate hook for drivers which don't have their own
512 : * subclassed connector state structure.
513 : */
514 : struct drm_connector_state *
515 0 : drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
516 : {
517 : struct drm_connector_state *state;
518 :
519 0 : if (WARN_ON(!connector->state))
520 : return NULL;
521 :
522 0 : state = kmalloc(sizeof(*state), GFP_KERNEL);
523 0 : if (state)
524 0 : __drm_atomic_helper_connector_duplicate_state(connector, state);
525 :
526 : return state;
527 : }
528 : EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
529 :
530 : /**
531 : * __drm_atomic_helper_connector_destroy_state - release connector state
532 : * @state: connector state object to release
533 : *
534 : * Releases all resources stored in the connector state without actually
535 : * freeing the memory of the connector state. This is useful for drivers that
536 : * subclass the connector state.
537 : */
538 : void
539 0 : __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
540 : {
541 0 : if (state->crtc)
542 0 : drm_connector_put(state->connector);
543 :
544 0 : if (state->commit)
545 0 : drm_crtc_commit_put(state->commit);
546 :
547 0 : if (state->writeback_job)
548 0 : drm_writeback_cleanup_job(state->writeback_job);
549 :
550 0 : drm_property_blob_put(state->hdr_output_metadata);
551 0 : }
552 : EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
553 :
554 : /**
555 : * drm_atomic_helper_connector_destroy_state - default state destroy hook
556 : * @connector: drm connector
557 : * @state: connector state object to release
558 : *
559 : * Default connector state destroy hook for drivers which don't have their own
560 : * subclassed connector state structure.
561 : */
562 0 : void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
563 : struct drm_connector_state *state)
564 : {
565 0 : __drm_atomic_helper_connector_destroy_state(state);
566 0 : kfree(state);
567 0 : }
568 : EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
569 :
570 : /**
571 : * __drm_atomic_helper_private_obj_duplicate_state - copy atomic private state
572 : * @obj: CRTC object
573 : * @state: new private object state
574 : *
575 : * Copies atomic state from a private objects's current state and resets inferred values.
576 : * This is useful for drivers that subclass the private state.
577 : */
578 0 : void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
579 : struct drm_private_state *state)
580 : {
581 0 : memcpy(state, obj->state, sizeof(*state));
582 0 : }
583 : EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state);
584 :
585 : /**
586 : * __drm_atomic_helper_bridge_duplicate_state() - Copy atomic bridge state
587 : * @bridge: bridge object
588 : * @state: atomic bridge state
589 : *
590 : * Copies atomic state from a bridge's current state and resets inferred values.
591 : * This is useful for drivers that subclass the bridge state.
592 : */
593 0 : void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
594 : struct drm_bridge_state *state)
595 : {
596 0 : __drm_atomic_helper_private_obj_duplicate_state(&bridge->base,
597 : &state->base);
598 0 : state->bridge = bridge;
599 0 : }
600 : EXPORT_SYMBOL(__drm_atomic_helper_bridge_duplicate_state);
601 :
602 : /**
603 : * drm_atomic_helper_bridge_duplicate_state() - Duplicate a bridge state object
604 : * @bridge: bridge object
605 : *
606 : * Allocates a new bridge state and initializes it with the current bridge
607 : * state values. This helper is meant to be used as a bridge
608 : * &drm_bridge_funcs.atomic_duplicate_state hook for bridges that don't
609 : * subclass the bridge state.
610 : */
611 : struct drm_bridge_state *
612 0 : drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge)
613 : {
614 : struct drm_bridge_state *new;
615 :
616 0 : if (WARN_ON(!bridge->base.state))
617 : return NULL;
618 :
619 0 : new = kzalloc(sizeof(*new), GFP_KERNEL);
620 0 : if (new)
621 : __drm_atomic_helper_bridge_duplicate_state(bridge, new);
622 :
623 : return new;
624 : }
625 : EXPORT_SYMBOL(drm_atomic_helper_bridge_duplicate_state);
626 :
627 : /**
628 : * drm_atomic_helper_bridge_destroy_state() - Destroy a bridge state object
629 : * @bridge: the bridge this state refers to
630 : * @state: bridge state to destroy
631 : *
632 : * Destroys a bridge state previously created by
633 : * &drm_atomic_helper_bridge_reset() or
634 : * &drm_atomic_helper_bridge_duplicate_state(). This helper is meant to be
635 : * used as a bridge &drm_bridge_funcs.atomic_destroy_state hook for bridges
636 : * that don't subclass the bridge state.
637 : */
638 0 : void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge,
639 : struct drm_bridge_state *state)
640 : {
641 0 : kfree(state);
642 0 : }
643 : EXPORT_SYMBOL(drm_atomic_helper_bridge_destroy_state);
644 :
645 : /**
646 : * __drm_atomic_helper_bridge_reset() - Initialize a bridge state to its
647 : * default
648 : * @bridge: the bridge this state refers to
649 : * @state: bridge state to initialize
650 : *
651 : * Initializes the bridge state to default values. This is meant to be called
652 : * by the bridge &drm_bridge_funcs.atomic_reset hook for bridges that subclass
653 : * the bridge state.
654 : */
655 0 : void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
656 : struct drm_bridge_state *state)
657 : {
658 0 : memset(state, 0, sizeof(*state));
659 0 : state->bridge = bridge;
660 0 : }
661 : EXPORT_SYMBOL(__drm_atomic_helper_bridge_reset);
662 :
663 : /**
664 : * drm_atomic_helper_bridge_reset() - Allocate and initialize a bridge state
665 : * to its default
666 : * @bridge: the bridge this state refers to
667 : *
668 : * Allocates the bridge state and initializes it to default values. This helper
669 : * is meant to be used as a bridge &drm_bridge_funcs.atomic_reset hook for
670 : * bridges that don't subclass the bridge state.
671 : */
672 : struct drm_bridge_state *
673 0 : drm_atomic_helper_bridge_reset(struct drm_bridge *bridge)
674 : {
675 : struct drm_bridge_state *bridge_state;
676 :
677 0 : bridge_state = kzalloc(sizeof(*bridge_state), GFP_KERNEL);
678 0 : if (!bridge_state)
679 : return ERR_PTR(-ENOMEM);
680 :
681 0 : __drm_atomic_helper_bridge_reset(bridge, bridge_state);
682 0 : return bridge_state;
683 : }
684 : EXPORT_SYMBOL(drm_atomic_helper_bridge_reset);
|