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
48869 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->color_pipeline_property) {
272
/* default is always NULL, i.e., bypass */
273
plane_state->color_pipeline = NULL;
274
}
275
276
if (plane->zpos_property) {
277
if (!drm_object_property_get_default_value(&plane->base,
278
plane->zpos_property,
279
&val)) {
280
plane_state->zpos = val;
281
plane_state->normalized_zpos = val;
282
}
283
}
284
285
if (plane->hotspot_x_property) {
286
if (!drm_object_property_get_default_value(&plane->base,
287
plane->hotspot_x_property,
288
&val))
289
plane_state->hotspot_x = val;
290
}
291
292
if (plane->hotspot_y_property) {
293
if (!drm_object_property_get_default_value(&plane->base,
294
plane->hotspot_y_property,
295
&val))
296
plane_state->hotspot_y = val;
297
}
298
}
299
EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset);
300
301
/**
302
* __drm_atomic_helper_plane_reset - reset state on plane
303
* @plane: drm plane
304
* @plane_state: plane state to assign
305
*
306
* Initializes the newly allocated @plane_state and assigns it to
307
* the &drm_crtc->state pointer of @plane, usually required when
308
* initializing the drivers or when called from the &drm_plane_funcs.reset
309
* hook.
310
*
311
* This is useful for drivers that subclass the plane state.
312
*/
313
void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
314
struct drm_plane_state *plane_state)
315
{
316
if (plane_state)
317
__drm_atomic_helper_plane_state_reset(plane_state, plane);
318
319
plane->state = plane_state;
320
}
321
EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
322
323
/**
324
* drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
325
* @plane: drm plane
326
*
327
* Resets the atomic state for @plane by freeing the state pointer (which might
328
* be NULL, e.g. at driver load time) and allocating a new empty state object.
329
*/
330
void drm_atomic_helper_plane_reset(struct drm_plane *plane)
331
{
332
if (plane->state)
333
__drm_atomic_helper_plane_destroy_state(plane->state);
334
335
kfree(plane->state);
336
plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
337
if (plane->state)
338
__drm_atomic_helper_plane_reset(plane, plane->state);
339
}
340
EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
341
342
/**
343
* __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
344
* @plane: plane object
345
* @state: atomic plane state
346
*
347
* Copies atomic state from a plane's current state. This is useful for
348
* drivers that subclass the plane state.
349
*/
350
void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
351
struct drm_plane_state *state)
352
{
353
memcpy(state, plane->state, sizeof(*state));
354
355
if (state->fb)
356
drm_framebuffer_get(state->fb);
357
358
state->fence = NULL;
359
state->commit = NULL;
360
state->fb_damage_clips = NULL;
361
state->color_mgmt_changed = false;
362
}
363
EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
364
365
/**
366
* drm_atomic_helper_plane_duplicate_state - default state duplicate hook
367
* @plane: drm plane
368
*
369
* Default plane state duplicate hook for drivers which don't have their own
370
* subclassed plane state structure.
371
*/
372
struct drm_plane_state *
373
drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
374
{
375
struct drm_plane_state *state;
376
377
if (WARN_ON(!plane->state))
378
return NULL;
379
380
state = kmalloc(sizeof(*state), GFP_KERNEL);
381
if (state)
382
__drm_atomic_helper_plane_duplicate_state(plane, state);
383
384
return state;
385
}
386
EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
387
388
/**
389
* __drm_atomic_helper_plane_destroy_state - release plane state
390
* @state: plane state object to release
391
*
392
* Releases all resources stored in the plane state without actually freeing
393
* the memory of the plane state. This is useful for drivers that subclass the
394
* plane state.
395
*/
396
void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
397
{
398
if (state->fb)
399
drm_framebuffer_put(state->fb);
400
401
if (state->fence)
402
dma_fence_put(state->fence);
403
404
if (state->commit)
405
drm_crtc_commit_put(state->commit);
406
407
drm_property_blob_put(state->fb_damage_clips);
408
}
409
EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
410
411
/**
412
* drm_atomic_helper_plane_destroy_state - default state destroy hook
413
* @plane: drm plane
414
* @state: plane state object to release
415
*
416
* Default plane state destroy hook for drivers which don't have their own
417
* subclassed plane state structure.
418
*/
419
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
420
struct drm_plane_state *state)
421
{
422
__drm_atomic_helper_plane_destroy_state(state);
423
kfree(state);
424
}
425
EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
426
427
/**
428
* __drm_atomic_helper_connector_state_reset - reset the connector state
429
* @conn_state: atomic connector state, must not be NULL
430
* @connector: connectotr object, must not be NULL
431
*
432
* Initializes the newly allocated @conn_state with default
433
* values. This is useful for drivers that subclass the connector state.
434
*/
435
void
436
__drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state,
437
struct drm_connector *connector)
438
{
439
conn_state->connector = connector;
440
}
441
EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset);
442
443
/**
444
* __drm_atomic_helper_connector_reset - reset state on connector
445
* @connector: drm connector
446
* @conn_state: connector state to assign
447
*
448
* Initializes the newly allocated @conn_state and assigns it to
449
* the &drm_connector->state pointer of @connector, usually required when
450
* initializing the drivers or when called from the &drm_connector_funcs.reset
451
* hook.
452
*
453
* This is useful for drivers that subclass the connector state.
454
*/
455
void
456
__drm_atomic_helper_connector_reset(struct drm_connector *connector,
457
struct drm_connector_state *conn_state)
458
{
459
if (conn_state)
460
__drm_atomic_helper_connector_state_reset(conn_state, connector);
461
462
connector->state = conn_state;
463
}
464
EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
465
466
/**
467
* drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
468
* @connector: drm connector
469
*
470
* Resets the atomic state for @connector by freeing the state pointer (which
471
* might be NULL, e.g. at driver load time) and allocating a new empty state
472
* object.
473
*/
474
void drm_atomic_helper_connector_reset(struct drm_connector *connector)
475
{
476
struct drm_connector_state *conn_state =
477
kzalloc(sizeof(*conn_state), GFP_KERNEL);
478
479
if (connector->state)
480
__drm_atomic_helper_connector_destroy_state(connector->state);
481
482
kfree(connector->state);
483
__drm_atomic_helper_connector_reset(connector, conn_state);
484
}
485
EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
486
487
/**
488
* drm_atomic_helper_connector_tv_margins_reset - Resets TV connector properties
489
* @connector: DRM connector
490
*
491
* Resets the TV-related properties attached to a connector.
492
*/
493
void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector)
494
{
495
struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
496
struct drm_connector_state *state = connector->state;
497
498
state->tv.margins.left = cmdline->tv_margins.left;
499
state->tv.margins.right = cmdline->tv_margins.right;
500
state->tv.margins.top = cmdline->tv_margins.top;
501
state->tv.margins.bottom = cmdline->tv_margins.bottom;
502
}
503
EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
504
505
/**
506
* drm_atomic_helper_connector_tv_reset - Resets Analog TV connector properties
507
* @connector: DRM connector
508
*
509
* Resets the analog TV properties attached to a connector
510
*/
511
void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
512
{
513
struct drm_device *dev = connector->dev;
514
struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
515
struct drm_connector_state *state = connector->state;
516
struct drm_property *prop;
517
uint64_t val;
518
519
prop = dev->mode_config.tv_mode_property;
520
if (prop)
521
if (!drm_object_property_get_default_value(&connector->base,
522
prop, &val))
523
state->tv.mode = val;
524
525
if (cmdline->tv_mode_specified)
526
state->tv.mode = cmdline->tv_mode;
527
528
prop = dev->mode_config.tv_select_subconnector_property;
529
if (prop)
530
if (!drm_object_property_get_default_value(&connector->base,
531
prop, &val))
532
state->tv.select_subconnector = val;
533
534
prop = dev->mode_config.tv_subconnector_property;
535
if (prop)
536
if (!drm_object_property_get_default_value(&connector->base,
537
prop, &val))
538
state->tv.subconnector = val;
539
540
prop = dev->mode_config.tv_brightness_property;
541
if (prop)
542
if (!drm_object_property_get_default_value(&connector->base,
543
prop, &val))
544
state->tv.brightness = val;
545
546
prop = dev->mode_config.tv_contrast_property;
547
if (prop)
548
if (!drm_object_property_get_default_value(&connector->base,
549
prop, &val))
550
state->tv.contrast = val;
551
552
prop = dev->mode_config.tv_flicker_reduction_property;
553
if (prop)
554
if (!drm_object_property_get_default_value(&connector->base,
555
prop, &val))
556
state->tv.flicker_reduction = val;
557
558
prop = dev->mode_config.tv_overscan_property;
559
if (prop)
560
if (!drm_object_property_get_default_value(&connector->base,
561
prop, &val))
562
state->tv.overscan = val;
563
564
prop = dev->mode_config.tv_saturation_property;
565
if (prop)
566
if (!drm_object_property_get_default_value(&connector->base,
567
prop, &val))
568
state->tv.saturation = val;
569
570
prop = dev->mode_config.tv_hue_property;
571
if (prop)
572
if (!drm_object_property_get_default_value(&connector->base,
573
prop, &val))
574
state->tv.hue = val;
575
576
drm_atomic_helper_connector_tv_margins_reset(connector);
577
}
578
EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
579
580
/**
581
* drm_atomic_helper_connector_tv_check - Validate an analog TV connector state
582
* @connector: DRM Connector
583
* @state: the DRM State object
584
*
585
* Checks the state object to see if the requested state is valid for an
586
* analog TV connector.
587
*
588
* Return:
589
* %0 for success, a negative error code on error.
590
*/
591
int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
592
struct drm_atomic_state *state)
593
{
594
struct drm_connector_state *old_conn_state =
595
drm_atomic_get_old_connector_state(state, connector);
596
struct drm_connector_state *new_conn_state =
597
drm_atomic_get_new_connector_state(state, connector);
598
struct drm_crtc_state *crtc_state;
599
struct drm_crtc *crtc;
600
601
crtc = new_conn_state->crtc;
602
if (!crtc)
603
return 0;
604
605
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
606
if (!crtc_state)
607
return -EINVAL;
608
609
if (old_conn_state->tv.mode != new_conn_state->tv.mode)
610
crtc_state->mode_changed = true;
611
612
if (old_conn_state->tv.margins.left != new_conn_state->tv.margins.left ||
613
old_conn_state->tv.margins.right != new_conn_state->tv.margins.right ||
614
old_conn_state->tv.margins.top != new_conn_state->tv.margins.top ||
615
old_conn_state->tv.margins.bottom != new_conn_state->tv.margins.bottom ||
616
old_conn_state->tv.mode != new_conn_state->tv.mode ||
617
old_conn_state->tv.brightness != new_conn_state->tv.brightness ||
618
old_conn_state->tv.contrast != new_conn_state->tv.contrast ||
619
old_conn_state->tv.flicker_reduction != new_conn_state->tv.flicker_reduction ||
620
old_conn_state->tv.overscan != new_conn_state->tv.overscan ||
621
old_conn_state->tv.saturation != new_conn_state->tv.saturation ||
622
old_conn_state->tv.hue != new_conn_state->tv.hue)
623
crtc_state->connectors_changed = true;
624
625
return 0;
626
}
627
EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
628
629
/**
630
* __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
631
* @connector: connector object
632
* @state: atomic connector state
633
*
634
* Copies atomic state from a connector's current state. This is useful for
635
* drivers that subclass the connector state.
636
*/
637
void
638
__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
639
struct drm_connector_state *state)
640
{
641
memcpy(state, connector->state, sizeof(*state));
642
if (state->crtc)
643
drm_connector_get(connector);
644
state->commit = NULL;
645
646
if (state->hdr_output_metadata)
647
drm_property_blob_get(state->hdr_output_metadata);
648
649
/* Don't copy over a writeback job, they are used only once */
650
state->writeback_job = NULL;
651
}
652
EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
653
654
/**
655
* drm_atomic_helper_connector_duplicate_state - default state duplicate hook
656
* @connector: drm connector
657
*
658
* Default connector state duplicate hook for drivers which don't have their own
659
* subclassed connector state structure.
660
*/
661
struct drm_connector_state *
662
drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
663
{
664
struct drm_connector_state *state;
665
666
if (WARN_ON(!connector->state))
667
return NULL;
668
669
state = kmalloc(sizeof(*state), GFP_KERNEL);
670
if (state)
671
__drm_atomic_helper_connector_duplicate_state(connector, state);
672
673
return state;
674
}
675
EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
676
677
/**
678
* __drm_atomic_helper_connector_destroy_state - release connector state
679
* @state: connector state object to release
680
*
681
* Releases all resources stored in the connector state without actually
682
* freeing the memory of the connector state. This is useful for drivers that
683
* subclass the connector state.
684
*/
685
void
686
__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
687
{
688
if (state->crtc)
689
drm_connector_put(state->connector);
690
691
if (state->commit)
692
drm_crtc_commit_put(state->commit);
693
694
if (state->writeback_job)
695
drm_writeback_cleanup_job(state->writeback_job);
696
697
drm_property_blob_put(state->hdr_output_metadata);
698
}
699
EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
700
701
/**
702
* drm_atomic_helper_connector_destroy_state - default state destroy hook
703
* @connector: drm connector
704
* @state: connector state object to release
705
*
706
* Default connector state destroy hook for drivers which don't have their own
707
* subclassed connector state structure.
708
*/
709
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
710
struct drm_connector_state *state)
711
{
712
__drm_atomic_helper_connector_destroy_state(state);
713
kfree(state);
714
}
715
EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
716
717
/**
718
* __drm_atomic_helper_private_obj_duplicate_state - copy atomic private state
719
* @obj: CRTC object
720
* @state: new private object state
721
*
722
* Copies atomic state from a private objects's current state and resets inferred values.
723
* This is useful for drivers that subclass the private state.
724
*/
725
void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
726
struct drm_private_state *state)
727
{
728
memcpy(state, obj->state, sizeof(*state));
729
}
730
EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state);
731
732
/**
733
* __drm_atomic_helper_bridge_duplicate_state() - Copy atomic bridge state
734
* @bridge: bridge object
735
* @state: atomic bridge state
736
*
737
* Copies atomic state from a bridge's current state and resets inferred values.
738
* This is useful for drivers that subclass the bridge state.
739
*/
740
void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
741
struct drm_bridge_state *state)
742
{
743
__drm_atomic_helper_private_obj_duplicate_state(&bridge->base,
744
&state->base);
745
state->bridge = bridge;
746
}
747
EXPORT_SYMBOL(__drm_atomic_helper_bridge_duplicate_state);
748
749
/**
750
* drm_atomic_helper_bridge_duplicate_state() - Duplicate a bridge state object
751
* @bridge: bridge object
752
*
753
* Allocates a new bridge state and initializes it with the current bridge
754
* state values. This helper is meant to be used as a bridge
755
* &drm_bridge_funcs.atomic_duplicate_state hook for bridges that don't
756
* subclass the bridge state.
757
*/
758
struct drm_bridge_state *
759
drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge)
760
{
761
struct drm_bridge_state *new;
762
763
if (WARN_ON(!bridge->base.state))
764
return NULL;
765
766
new = kzalloc(sizeof(*new), GFP_KERNEL);
767
if (new)
768
__drm_atomic_helper_bridge_duplicate_state(bridge, new);
769
770
return new;
771
}
772
EXPORT_SYMBOL(drm_atomic_helper_bridge_duplicate_state);
773
774
/**
775
* drm_atomic_helper_bridge_destroy_state() - Destroy a bridge state object
776
* @bridge: the bridge this state refers to
777
* @state: bridge state to destroy
778
*
779
* Destroys a bridge state previously created by
780
* &drm_atomic_helper_bridge_reset() or
781
* &drm_atomic_helper_bridge_duplicate_state(). This helper is meant to be
782
* used as a bridge &drm_bridge_funcs.atomic_destroy_state hook for bridges
783
* that don't subclass the bridge state.
784
*/
785
void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge,
786
struct drm_bridge_state *state)
787
{
788
kfree(state);
789
}
790
EXPORT_SYMBOL(drm_atomic_helper_bridge_destroy_state);
791
792
/**
793
* __drm_atomic_helper_bridge_reset() - Initialize a bridge state to its
794
* default
795
* @bridge: the bridge this state refers to
796
* @state: bridge state to initialize
797
*
798
* Initializes the bridge state to default values. This is meant to be called
799
* by the bridge &drm_bridge_funcs.atomic_reset hook for bridges that subclass
800
* the bridge state.
801
*/
802
void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
803
struct drm_bridge_state *state)
804
{
805
memset(state, 0, sizeof(*state));
806
state->bridge = bridge;
807
}
808
EXPORT_SYMBOL(__drm_atomic_helper_bridge_reset);
809
810
/**
811
* drm_atomic_helper_bridge_reset() - Allocate and initialize a bridge state
812
* to its default
813
* @bridge: the bridge this state refers to
814
*
815
* Allocates the bridge state and initializes it to default values. This helper
816
* is meant to be used as a bridge &drm_bridge_funcs.atomic_reset hook for
817
* bridges that don't subclass the bridge state.
818
*/
819
struct drm_bridge_state *
820
drm_atomic_helper_bridge_reset(struct drm_bridge *bridge)
821
{
822
struct drm_bridge_state *bridge_state;
823
824
bridge_state = kzalloc(sizeof(*bridge_state), GFP_KERNEL);
825
if (!bridge_state)
826
return ERR_PTR(-ENOMEM);
827
828
__drm_atomic_helper_bridge_reset(bridge, bridge_state);
829
return bridge_state;
830
}
831
EXPORT_SYMBOL(drm_atomic_helper_bridge_reset);
832
833