Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/drm_atomic_state_helper.c
26428 views
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 <[email protected]>
24
* Daniel Vetter <[email protected]>
25
*/
26
27
#include <drm/drm_atomic.h>
28
#include <drm/drm_atomic_state_helper.h>
29
#include <drm/drm_blend.h>
30
#include <drm/drm_bridge.h>
31
#include <drm/drm_connector.h>
32
#include <drm/drm_crtc.h>
33
#include <drm/drm_device.h>
34
#include <drm/drm_framebuffer.h>
35
#include <drm/drm_plane.h>
36
#include <drm/drm_print.h>
37
#include <drm/drm_vblank.h>
38
#include <drm/drm_writeback.h>
39
40
#include <linux/export.h>
41
#include <linux/slab.h>
42
#include <linux/dma-fence.h>
43
44
/**
45
* DOC: atomic state reset and initialization
46
*
47
* Both the drm core and the atomic helpers assume that there is always the full
48
* and correct atomic software state for all connectors, CRTCs and planes
49
* available. Which is a bit a problem on driver load and also after system
50
* suspend. One way to solve this is to have a hardware state read-out
51
* infrastructure which reconstructs the full software state (e.g. the i915
52
* driver).
53
*
54
* The simpler solution is to just reset the software state to everything off,
55
* which is easiest to do by calling drm_mode_config_reset(). To facilitate this
56
* the atomic helpers provide default reset implementations for all hooks.
57
*
58
* On the upside the precise state tracking of atomic simplifies system suspend
59
* and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
60
* is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
61
* For other drivers the building blocks are split out, see the documentation
62
* for these functions.
63
*/
64
65
/**
66
* __drm_atomic_helper_crtc_state_reset - reset the CRTC state
67
* @crtc_state: atomic CRTC state, must not be NULL
68
* @crtc: CRTC object, must not be NULL
69
*
70
* Initializes the newly allocated @crtc_state with default
71
* values. This is useful for drivers that subclass the CRTC state.
72
*/
73
void
74
__drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state,
75
struct drm_crtc *crtc)
76
{
77
crtc_state->crtc = crtc;
78
}
79
EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset);
80
81
/**
82
* __drm_atomic_helper_crtc_reset - reset state on CRTC
83
* @crtc: drm CRTC
84
* @crtc_state: CRTC state to assign
85
*
86
* Initializes the newly allocated @crtc_state and assigns it to
87
* the &drm_crtc->state pointer of @crtc, usually required when
88
* initializing the drivers or when called from the &drm_crtc_funcs.reset
89
* hook.
90
*
91
* This is useful for drivers that subclass the CRTC state.
92
*/
93
void
94
__drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
95
struct drm_crtc_state *crtc_state)
96
{
97
if (crtc_state)
98
__drm_atomic_helper_crtc_state_reset(crtc_state, crtc);
99
100
if (drm_dev_has_vblank(crtc->dev))
101
drm_crtc_vblank_reset(crtc);
102
103
crtc->state = crtc_state;
104
}
105
EXPORT_SYMBOL(__drm_atomic_helper_crtc_reset);
106
107
/**
108
* drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
109
* @crtc: drm CRTC
110
*
111
* Resets the atomic state for @crtc by freeing the state pointer (which might
112
* be NULL, e.g. at driver load time) and allocating a new empty state object.
113
*/
114
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
115
{
116
struct drm_crtc_state *crtc_state =
117
kzalloc(sizeof(*crtc->state), GFP_KERNEL);
118
119
if (crtc->state)
120
crtc->funcs->atomic_destroy_state(crtc, crtc->state);
121
122
__drm_atomic_helper_crtc_reset(crtc, crtc_state);
123
}
124
EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
125
126
/**
127
* __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
128
* @crtc: CRTC object
129
* @state: atomic CRTC state
130
*
131
* Copies atomic state from a CRTC's current state and resets inferred values.
132
* This is useful for drivers that subclass the CRTC state.
133
*/
134
void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
135
struct drm_crtc_state *state)
136
{
137
memcpy(state, crtc->state, sizeof(*state));
138
139
if (state->mode_blob)
140
drm_property_blob_get(state->mode_blob);
141
if (state->degamma_lut)
142
drm_property_blob_get(state->degamma_lut);
143
if (state->ctm)
144
drm_property_blob_get(state->ctm);
145
if (state->gamma_lut)
146
drm_property_blob_get(state->gamma_lut);
147
state->mode_changed = false;
148
state->active_changed = false;
149
state->planes_changed = false;
150
state->connectors_changed = false;
151
state->color_mgmt_changed = false;
152
state->zpos_changed = false;
153
state->commit = NULL;
154
state->event = NULL;
155
state->async_flip = false;
156
157
/* Self refresh should be canceled when a new update is available */
158
state->active = drm_atomic_crtc_effectively_active(state);
159
state->self_refresh_active = false;
160
}
161
EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
162
163
/**
164
* drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
165
* @crtc: drm CRTC
166
*
167
* Default CRTC state duplicate hook for drivers which don't have their own
168
* subclassed CRTC state structure.
169
*/
170
struct drm_crtc_state *
171
drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
172
{
173
struct drm_crtc_state *state;
174
175
if (WARN_ON(!crtc->state))
176
return NULL;
177
178
state = kmalloc(sizeof(*state), GFP_KERNEL);
179
if (state)
180
__drm_atomic_helper_crtc_duplicate_state(crtc, state);
181
182
return state;
183
}
184
EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
185
186
/**
187
* __drm_atomic_helper_crtc_destroy_state - release CRTC state
188
* @state: CRTC state object to release
189
*
190
* Releases all resources stored in the CRTC state without actually freeing
191
* the memory of the CRTC state. This is useful for drivers that subclass the
192
* CRTC state.
193
*/
194
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
195
{
196
if (state->commit) {
197
/*
198
* In the event that a non-blocking commit returns
199
* -ERESTARTSYS before the commit_tail work is queued, we will
200
* have an extra reference to the commit object. Release it, if
201
* the event has not been consumed by the worker.
202
*
203
* state->event may be freed, so we can't directly look at
204
* state->event->base.completion.
205
*/
206
if (state->event && state->commit->abort_completion)
207
drm_crtc_commit_put(state->commit);
208
209
kfree(state->commit->event);
210
state->commit->event = NULL;
211
212
drm_crtc_commit_put(state->commit);
213
}
214
215
drm_property_blob_put(state->mode_blob);
216
drm_property_blob_put(state->degamma_lut);
217
drm_property_blob_put(state->ctm);
218
drm_property_blob_put(state->gamma_lut);
219
}
220
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
221
222
/**
223
* drm_atomic_helper_crtc_destroy_state - default state destroy hook
224
* @crtc: drm CRTC
225
* @state: CRTC state object to release
226
*
227
* Default CRTC state destroy hook for drivers which don't have their own
228
* subclassed CRTC state structure.
229
*/
230
void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
231
struct drm_crtc_state *state)
232
{
233
__drm_atomic_helper_crtc_destroy_state(state);
234
kfree(state);
235
}
236
EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
237
238
/**
239
* __drm_atomic_helper_plane_state_reset - resets plane state to default values
240
* @plane_state: atomic plane state, must not be NULL
241
* @plane: plane object, must not be NULL
242
*
243
* Initializes the newly allocated @plane_state with default
244
* values. This is useful for drivers that subclass the CRTC state.
245
*/
246
void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state,
247
struct drm_plane *plane)
248
{
249
u64 val;
250
251
plane_state->plane = plane;
252
plane_state->rotation = DRM_MODE_ROTATE_0;
253
254
plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE;
255
plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
256
257
if (plane->color_encoding_property) {
258
if (!drm_object_property_get_default_value(&plane->base,
259
plane->color_encoding_property,
260
&val))
261
plane_state->color_encoding = val;
262
}
263
264
if (plane->color_range_property) {
265
if (!drm_object_property_get_default_value(&plane->base,
266
plane->color_range_property,
267
&val))
268
plane_state->color_range = val;
269
}
270
271
if (plane->zpos_property) {
272
if (!drm_object_property_get_default_value(&plane->base,
273
plane->zpos_property,
274
&val)) {
275
plane_state->zpos = val;
276
plane_state->normalized_zpos = val;
277
}
278
}
279
280
if (plane->hotspot_x_property) {
281
if (!drm_object_property_get_default_value(&plane->base,
282
plane->hotspot_x_property,
283
&val))
284
plane_state->hotspot_x = val;
285
}
286
287
if (plane->hotspot_y_property) {
288
if (!drm_object_property_get_default_value(&plane->base,
289
plane->hotspot_y_property,
290
&val))
291
plane_state->hotspot_y = val;
292
}
293
}
294
EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset);
295
296
/**
297
* __drm_atomic_helper_plane_reset - reset state on plane
298
* @plane: drm plane
299
* @plane_state: plane state to assign
300
*
301
* Initializes the newly allocated @plane_state and assigns it to
302
* the &drm_crtc->state pointer of @plane, usually required when
303
* initializing the drivers or when called from the &drm_plane_funcs.reset
304
* hook.
305
*
306
* This is useful for drivers that subclass the plane state.
307
*/
308
void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
309
struct drm_plane_state *plane_state)
310
{
311
if (plane_state)
312
__drm_atomic_helper_plane_state_reset(plane_state, plane);
313
314
plane->state = plane_state;
315
}
316
EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
317
318
/**
319
* drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
320
* @plane: drm plane
321
*
322
* Resets the atomic state for @plane by freeing the state pointer (which might
323
* be NULL, e.g. at driver load time) and allocating a new empty state object.
324
*/
325
void drm_atomic_helper_plane_reset(struct drm_plane *plane)
326
{
327
if (plane->state)
328
__drm_atomic_helper_plane_destroy_state(plane->state);
329
330
kfree(plane->state);
331
plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
332
if (plane->state)
333
__drm_atomic_helper_plane_reset(plane, plane->state);
334
}
335
EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
336
337
/**
338
* __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
339
* @plane: plane object
340
* @state: atomic plane state
341
*
342
* Copies atomic state from a plane's current state. This is useful for
343
* drivers that subclass the plane state.
344
*/
345
void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
346
struct drm_plane_state *state)
347
{
348
memcpy(state, plane->state, sizeof(*state));
349
350
if (state->fb)
351
drm_framebuffer_get(state->fb);
352
353
state->fence = NULL;
354
state->commit = NULL;
355
state->fb_damage_clips = NULL;
356
state->color_mgmt_changed = false;
357
}
358
EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
359
360
/**
361
* drm_atomic_helper_plane_duplicate_state - default state duplicate hook
362
* @plane: drm plane
363
*
364
* Default plane state duplicate hook for drivers which don't have their own
365
* subclassed plane state structure.
366
*/
367
struct drm_plane_state *
368
drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
369
{
370
struct drm_plane_state *state;
371
372
if (WARN_ON(!plane->state))
373
return NULL;
374
375
state = kmalloc(sizeof(*state), GFP_KERNEL);
376
if (state)
377
__drm_atomic_helper_plane_duplicate_state(plane, state);
378
379
return state;
380
}
381
EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
382
383
/**
384
* __drm_atomic_helper_plane_destroy_state - release plane state
385
* @state: plane state object to release
386
*
387
* Releases all resources stored in the plane state without actually freeing
388
* the memory of the plane state. This is useful for drivers that subclass the
389
* plane state.
390
*/
391
void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
392
{
393
if (state->fb)
394
drm_framebuffer_put(state->fb);
395
396
if (state->fence)
397
dma_fence_put(state->fence);
398
399
if (state->commit)
400
drm_crtc_commit_put(state->commit);
401
402
drm_property_blob_put(state->fb_damage_clips);
403
}
404
EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
405
406
/**
407
* drm_atomic_helper_plane_destroy_state - default state destroy hook
408
* @plane: drm plane
409
* @state: plane state object to release
410
*
411
* Default plane state destroy hook for drivers which don't have their own
412
* subclassed plane state structure.
413
*/
414
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
415
struct drm_plane_state *state)
416
{
417
__drm_atomic_helper_plane_destroy_state(state);
418
kfree(state);
419
}
420
EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
421
422
/**
423
* __drm_atomic_helper_connector_state_reset - reset the connector state
424
* @conn_state: atomic connector state, must not be NULL
425
* @connector: connectotr object, must not be NULL
426
*
427
* Initializes the newly allocated @conn_state with default
428
* values. This is useful for drivers that subclass the connector state.
429
*/
430
void
431
__drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state,
432
struct drm_connector *connector)
433
{
434
conn_state->connector = connector;
435
}
436
EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset);
437
438
/**
439
* __drm_atomic_helper_connector_reset - reset state on connector
440
* @connector: drm connector
441
* @conn_state: connector state to assign
442
*
443
* Initializes the newly allocated @conn_state and assigns it to
444
* the &drm_connector->state pointer of @connector, usually required when
445
* initializing the drivers or when called from the &drm_connector_funcs.reset
446
* hook.
447
*
448
* This is useful for drivers that subclass the connector state.
449
*/
450
void
451
__drm_atomic_helper_connector_reset(struct drm_connector *connector,
452
struct drm_connector_state *conn_state)
453
{
454
if (conn_state)
455
__drm_atomic_helper_connector_state_reset(conn_state, connector);
456
457
connector->state = conn_state;
458
}
459
EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
460
461
/**
462
* drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
463
* @connector: drm connector
464
*
465
* Resets the atomic state for @connector by freeing the state pointer (which
466
* might be NULL, e.g. at driver load time) and allocating a new empty state
467
* object.
468
*/
469
void drm_atomic_helper_connector_reset(struct drm_connector *connector)
470
{
471
struct drm_connector_state *conn_state =
472
kzalloc(sizeof(*conn_state), GFP_KERNEL);
473
474
if (connector->state)
475
__drm_atomic_helper_connector_destroy_state(connector->state);
476
477
kfree(connector->state);
478
__drm_atomic_helper_connector_reset(connector, conn_state);
479
}
480
EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
481
482
/**
483
* drm_atomic_helper_connector_tv_margins_reset - Resets TV connector properties
484
* @connector: DRM connector
485
*
486
* Resets the TV-related properties attached to a connector.
487
*/
488
void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector)
489
{
490
struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
491
struct drm_connector_state *state = connector->state;
492
493
state->tv.margins.left = cmdline->tv_margins.left;
494
state->tv.margins.right = cmdline->tv_margins.right;
495
state->tv.margins.top = cmdline->tv_margins.top;
496
state->tv.margins.bottom = cmdline->tv_margins.bottom;
497
}
498
EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
499
500
/**
501
* drm_atomic_helper_connector_tv_reset - Resets Analog TV connector properties
502
* @connector: DRM connector
503
*
504
* Resets the analog TV properties attached to a connector
505
*/
506
void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
507
{
508
struct drm_device *dev = connector->dev;
509
struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
510
struct drm_connector_state *state = connector->state;
511
struct drm_property *prop;
512
uint64_t val;
513
514
prop = dev->mode_config.tv_mode_property;
515
if (prop)
516
if (!drm_object_property_get_default_value(&connector->base,
517
prop, &val))
518
state->tv.mode = val;
519
520
if (cmdline->tv_mode_specified)
521
state->tv.mode = cmdline->tv_mode;
522
523
prop = dev->mode_config.tv_select_subconnector_property;
524
if (prop)
525
if (!drm_object_property_get_default_value(&connector->base,
526
prop, &val))
527
state->tv.select_subconnector = val;
528
529
prop = dev->mode_config.tv_subconnector_property;
530
if (prop)
531
if (!drm_object_property_get_default_value(&connector->base,
532
prop, &val))
533
state->tv.subconnector = val;
534
535
prop = dev->mode_config.tv_brightness_property;
536
if (prop)
537
if (!drm_object_property_get_default_value(&connector->base,
538
prop, &val))
539
state->tv.brightness = val;
540
541
prop = dev->mode_config.tv_contrast_property;
542
if (prop)
543
if (!drm_object_property_get_default_value(&connector->base,
544
prop, &val))
545
state->tv.contrast = val;
546
547
prop = dev->mode_config.tv_flicker_reduction_property;
548
if (prop)
549
if (!drm_object_property_get_default_value(&connector->base,
550
prop, &val))
551
state->tv.flicker_reduction = val;
552
553
prop = dev->mode_config.tv_overscan_property;
554
if (prop)
555
if (!drm_object_property_get_default_value(&connector->base,
556
prop, &val))
557
state->tv.overscan = val;
558
559
prop = dev->mode_config.tv_saturation_property;
560
if (prop)
561
if (!drm_object_property_get_default_value(&connector->base,
562
prop, &val))
563
state->tv.saturation = val;
564
565
prop = dev->mode_config.tv_hue_property;
566
if (prop)
567
if (!drm_object_property_get_default_value(&connector->base,
568
prop, &val))
569
state->tv.hue = val;
570
571
drm_atomic_helper_connector_tv_margins_reset(connector);
572
}
573
EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
574
575
/**
576
* drm_atomic_helper_connector_tv_check - Validate an analog TV connector state
577
* @connector: DRM Connector
578
* @state: the DRM State object
579
*
580
* Checks the state object to see if the requested state is valid for an
581
* analog TV connector.
582
*
583
* Return:
584
* %0 for success, a negative error code on error.
585
*/
586
int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
587
struct drm_atomic_state *state)
588
{
589
struct drm_connector_state *old_conn_state =
590
drm_atomic_get_old_connector_state(state, connector);
591
struct drm_connector_state *new_conn_state =
592
drm_atomic_get_new_connector_state(state, connector);
593
struct drm_crtc_state *crtc_state;
594
struct drm_crtc *crtc;
595
596
crtc = new_conn_state->crtc;
597
if (!crtc)
598
return 0;
599
600
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
601
if (!crtc_state)
602
return -EINVAL;
603
604
if (old_conn_state->tv.mode != new_conn_state->tv.mode)
605
crtc_state->mode_changed = true;
606
607
if (old_conn_state->tv.margins.left != new_conn_state->tv.margins.left ||
608
old_conn_state->tv.margins.right != new_conn_state->tv.margins.right ||
609
old_conn_state->tv.margins.top != new_conn_state->tv.margins.top ||
610
old_conn_state->tv.margins.bottom != new_conn_state->tv.margins.bottom ||
611
old_conn_state->tv.mode != new_conn_state->tv.mode ||
612
old_conn_state->tv.brightness != new_conn_state->tv.brightness ||
613
old_conn_state->tv.contrast != new_conn_state->tv.contrast ||
614
old_conn_state->tv.flicker_reduction != new_conn_state->tv.flicker_reduction ||
615
old_conn_state->tv.overscan != new_conn_state->tv.overscan ||
616
old_conn_state->tv.saturation != new_conn_state->tv.saturation ||
617
old_conn_state->tv.hue != new_conn_state->tv.hue)
618
crtc_state->connectors_changed = true;
619
620
return 0;
621
}
622
EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
623
624
/**
625
* __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
626
* @connector: connector object
627
* @state: atomic connector state
628
*
629
* Copies atomic state from a connector's current state. This is useful for
630
* drivers that subclass the connector state.
631
*/
632
void
633
__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
634
struct drm_connector_state *state)
635
{
636
memcpy(state, connector->state, sizeof(*state));
637
if (state->crtc)
638
drm_connector_get(connector);
639
state->commit = NULL;
640
641
if (state->hdr_output_metadata)
642
drm_property_blob_get(state->hdr_output_metadata);
643
644
/* Don't copy over a writeback job, they are used only once */
645
state->writeback_job = NULL;
646
}
647
EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
648
649
/**
650
* drm_atomic_helper_connector_duplicate_state - default state duplicate hook
651
* @connector: drm connector
652
*
653
* Default connector state duplicate hook for drivers which don't have their own
654
* subclassed connector state structure.
655
*/
656
struct drm_connector_state *
657
drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
658
{
659
struct drm_connector_state *state;
660
661
if (WARN_ON(!connector->state))
662
return NULL;
663
664
state = kmalloc(sizeof(*state), GFP_KERNEL);
665
if (state)
666
__drm_atomic_helper_connector_duplicate_state(connector, state);
667
668
return state;
669
}
670
EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
671
672
/**
673
* __drm_atomic_helper_connector_destroy_state - release connector state
674
* @state: connector state object to release
675
*
676
* Releases all resources stored in the connector state without actually
677
* freeing the memory of the connector state. This is useful for drivers that
678
* subclass the connector state.
679
*/
680
void
681
__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
682
{
683
if (state->crtc)
684
drm_connector_put(state->connector);
685
686
if (state->commit)
687
drm_crtc_commit_put(state->commit);
688
689
if (state->writeback_job)
690
drm_writeback_cleanup_job(state->writeback_job);
691
692
drm_property_blob_put(state->hdr_output_metadata);
693
}
694
EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
695
696
/**
697
* drm_atomic_helper_connector_destroy_state - default state destroy hook
698
* @connector: drm connector
699
* @state: connector state object to release
700
*
701
* Default connector state destroy hook for drivers which don't have their own
702
* subclassed connector state structure.
703
*/
704
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
705
struct drm_connector_state *state)
706
{
707
__drm_atomic_helper_connector_destroy_state(state);
708
kfree(state);
709
}
710
EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
711
712
/**
713
* __drm_atomic_helper_private_obj_duplicate_state - copy atomic private state
714
* @obj: CRTC object
715
* @state: new private object state
716
*
717
* Copies atomic state from a private objects's current state and resets inferred values.
718
* This is useful for drivers that subclass the private state.
719
*/
720
void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
721
struct drm_private_state *state)
722
{
723
memcpy(state, obj->state, sizeof(*state));
724
}
725
EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state);
726
727
/**
728
* __drm_atomic_helper_bridge_duplicate_state() - Copy atomic bridge state
729
* @bridge: bridge object
730
* @state: atomic bridge state
731
*
732
* Copies atomic state from a bridge's current state and resets inferred values.
733
* This is useful for drivers that subclass the bridge state.
734
*/
735
void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
736
struct drm_bridge_state *state)
737
{
738
__drm_atomic_helper_private_obj_duplicate_state(&bridge->base,
739
&state->base);
740
state->bridge = bridge;
741
}
742
EXPORT_SYMBOL(__drm_atomic_helper_bridge_duplicate_state);
743
744
/**
745
* drm_atomic_helper_bridge_duplicate_state() - Duplicate a bridge state object
746
* @bridge: bridge object
747
*
748
* Allocates a new bridge state and initializes it with the current bridge
749
* state values. This helper is meant to be used as a bridge
750
* &drm_bridge_funcs.atomic_duplicate_state hook for bridges that don't
751
* subclass the bridge state.
752
*/
753
struct drm_bridge_state *
754
drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge)
755
{
756
struct drm_bridge_state *new;
757
758
if (WARN_ON(!bridge->base.state))
759
return NULL;
760
761
new = kzalloc(sizeof(*new), GFP_KERNEL);
762
if (new)
763
__drm_atomic_helper_bridge_duplicate_state(bridge, new);
764
765
return new;
766
}
767
EXPORT_SYMBOL(drm_atomic_helper_bridge_duplicate_state);
768
769
/**
770
* drm_atomic_helper_bridge_destroy_state() - Destroy a bridge state object
771
* @bridge: the bridge this state refers to
772
* @state: bridge state to destroy
773
*
774
* Destroys a bridge state previously created by
775
* &drm_atomic_helper_bridge_reset() or
776
* &drm_atomic_helper_bridge_duplicate_state(). This helper is meant to be
777
* used as a bridge &drm_bridge_funcs.atomic_destroy_state hook for bridges
778
* that don't subclass the bridge state.
779
*/
780
void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge,
781
struct drm_bridge_state *state)
782
{
783
kfree(state);
784
}
785
EXPORT_SYMBOL(drm_atomic_helper_bridge_destroy_state);
786
787
/**
788
* __drm_atomic_helper_bridge_reset() - Initialize a bridge state to its
789
* default
790
* @bridge: the bridge this state refers to
791
* @state: bridge state to initialize
792
*
793
* Initializes the bridge state to default values. This is meant to be called
794
* by the bridge &drm_bridge_funcs.atomic_reset hook for bridges that subclass
795
* the bridge state.
796
*/
797
void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
798
struct drm_bridge_state *state)
799
{
800
memset(state, 0, sizeof(*state));
801
state->bridge = bridge;
802
}
803
EXPORT_SYMBOL(__drm_atomic_helper_bridge_reset);
804
805
/**
806
* drm_atomic_helper_bridge_reset() - Allocate and initialize a bridge state
807
* to its default
808
* @bridge: the bridge this state refers to
809
*
810
* Allocates the bridge state and initializes it to default values. This helper
811
* is meant to be used as a bridge &drm_bridge_funcs.atomic_reset hook for
812
* bridges that don't subclass the bridge state.
813
*/
814
struct drm_bridge_state *
815
drm_atomic_helper_bridge_reset(struct drm_bridge *bridge)
816
{
817
struct drm_bridge_state *bridge_state;
818
819
bridge_state = kzalloc(sizeof(*bridge_state), GFP_KERNEL);
820
if (!bridge_state)
821
return ERR_PTR(-ENOMEM);
822
823
__drm_atomic_helper_bridge_reset(bridge, bridge_state);
824
return bridge_state;
825
}
826
EXPORT_SYMBOL(drm_atomic_helper_bridge_reset);
827
828