Home | History | Annotate | Line # | Download | only in drm
      1 /*	$NetBSD: drm_atomic_state_helper.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2018 Intel Corp.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  * Rob Clark <robdclark (at) gmail.com>
     26  * Daniel Vetter <daniel.vetter (at) ffwll.ch>
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: drm_atomic_state_helper.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $");
     31 
     32 #include <drm/drm_atomic.h>
     33 #include <drm/drm_atomic_state_helper.h>
     34 #include <drm/drm_connector.h>
     35 #include <drm/drm_crtc.h>
     36 #include <drm/drm_device.h>
     37 #include <drm/drm_plane.h>
     38 #include <drm/drm_print.h>
     39 #include <drm/drm_writeback.h>
     40 
     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 	crtc->state = crtc_state;
    101 }
    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 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
    112 {
    113 	struct drm_crtc_state *crtc_state =
    114 		kzalloc(sizeof(*crtc->state), GFP_KERNEL);
    115 
    116 	if (crtc->state)
    117 		crtc->funcs->atomic_destroy_state(crtc, crtc->state);
    118 
    119 	__drm_atomic_helper_crtc_reset(crtc, crtc_state);
    120 }
    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 void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
    132 					      struct drm_crtc_state *state)
    133 {
    134 	memcpy(state, crtc->state, sizeof(*state));
    135 
    136 	if (state->mode_blob)
    137 		drm_property_blob_get(state->mode_blob);
    138 	if (state->degamma_lut)
    139 		drm_property_blob_get(state->degamma_lut);
    140 	if (state->ctm)
    141 		drm_property_blob_get(state->ctm);
    142 	if (state->gamma_lut)
    143 		drm_property_blob_get(state->gamma_lut);
    144 	state->mode_changed = false;
    145 	state->active_changed = false;
    146 	state->planes_changed = false;
    147 	state->connectors_changed = false;
    148 	state->color_mgmt_changed = false;
    149 	state->zpos_changed = false;
    150 	state->commit = NULL;
    151 	state->event = NULL;
    152 	state->async_flip = false;
    153 
    154 	/* Self refresh should be canceled when a new update is available */
    155 	state->active = drm_atomic_crtc_effectively_active(state);
    156 	state->self_refresh_active = false;
    157 }
    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 drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
    169 {
    170 	struct drm_crtc_state *state;
    171 
    172 	if (WARN_ON(!crtc->state))
    173 		return NULL;
    174 
    175 	state = kmalloc(sizeof(*state), GFP_KERNEL);
    176 	if (state)
    177 		__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 void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
    192 {
    193 	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 		if (state->event && state->commit->abort_completion)
    204 			drm_crtc_commit_put(state->commit);
    205 
    206 		kfree(state->commit->event);
    207 		state->commit->event = NULL;
    208 
    209 		drm_crtc_commit_put(state->commit);
    210 	}
    211 
    212 	drm_property_blob_put(state->mode_blob);
    213 	drm_property_blob_put(state->degamma_lut);
    214 	drm_property_blob_put(state->ctm);
    215 	drm_property_blob_put(state->gamma_lut);
    216 }
    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 void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
    228 					  struct drm_crtc_state *state)
    229 {
    230 	__drm_atomic_helper_crtc_destroy_state(state);
    231 	kfree(state);
    232 }
    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 void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state,
    244 					   struct drm_plane *plane)
    245 {
    246 	plane_state->plane = plane;
    247 	plane_state->rotation = DRM_MODE_ROTATE_0;
    248 
    249 	plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE;
    250 	plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
    251 }
    252 EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset);
    253 
    254 /**
    255  * __drm_atomic_helper_plane_reset - reset state on plane
    256  * @plane: drm plane
    257  * @plane_state: plane state to assign
    258  *
    259  * Initializes the newly allocated @plane_state and assigns it to
    260  * the &drm_crtc->state pointer of @plane, usually required when
    261  * initializing the drivers or when called from the &drm_plane_funcs.reset
    262  * hook.
    263  *
    264  * This is useful for drivers that subclass the plane state.
    265  */
    266 void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
    267 				     struct drm_plane_state *plane_state)
    268 {
    269 	if (plane_state)
    270 		__drm_atomic_helper_plane_state_reset(plane_state, plane);
    271 
    272 	plane->state = plane_state;
    273 }
    274 EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
    275 
    276 /**
    277  * drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
    278  * @plane: drm plane
    279  *
    280  * Resets the atomic state for @plane by freeing the state pointer (which might
    281  * be NULL, e.g. at driver load time) and allocating a new empty state object.
    282  */
    283 void drm_atomic_helper_plane_reset(struct drm_plane *plane)
    284 {
    285 	if (plane->state)
    286 		__drm_atomic_helper_plane_destroy_state(plane->state);
    287 
    288 	kfree(plane->state);
    289 	plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
    290 	if (plane->state)
    291 		__drm_atomic_helper_plane_reset(plane, plane->state);
    292 }
    293 EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
    294 
    295 /**
    296  * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
    297  * @plane: plane object
    298  * @state: atomic plane state
    299  *
    300  * Copies atomic state from a plane's current state. This is useful for
    301  * drivers that subclass the plane state.
    302  */
    303 void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
    304 					       struct drm_plane_state *state)
    305 {
    306 	memcpy(state, plane->state, sizeof(*state));
    307 
    308 	if (state->fb)
    309 		drm_framebuffer_get(state->fb);
    310 
    311 	state->fence = NULL;
    312 	state->commit = NULL;
    313 	state->fb_damage_clips = NULL;
    314 }
    315 EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
    316 
    317 /**
    318  * drm_atomic_helper_plane_duplicate_state - default state duplicate hook
    319  * @plane: drm plane
    320  *
    321  * Default plane state duplicate hook for drivers which don't have their own
    322  * subclassed plane state structure.
    323  */
    324 struct drm_plane_state *
    325 drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
    326 {
    327 	struct drm_plane_state *state;
    328 
    329 	if (WARN_ON(!plane->state))
    330 		return NULL;
    331 
    332 	state = kmalloc(sizeof(*state), GFP_KERNEL);
    333 	if (state)
    334 		__drm_atomic_helper_plane_duplicate_state(plane, state);
    335 
    336 	return state;
    337 }
    338 EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
    339 
    340 /**
    341  * __drm_atomic_helper_plane_destroy_state - release plane state
    342  * @state: plane state object to release
    343  *
    344  * Releases all resources stored in the plane state without actually freeing
    345  * the memory of the plane state. This is useful for drivers that subclass the
    346  * plane state.
    347  */
    348 void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
    349 {
    350 	if (state->fb)
    351 		drm_framebuffer_put(state->fb);
    352 
    353 	if (state->fence)
    354 		dma_fence_put(state->fence);
    355 
    356 	if (state->commit)
    357 		drm_crtc_commit_put(state->commit);
    358 
    359 	drm_property_blob_put(state->fb_damage_clips);
    360 }
    361 EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
    362 
    363 /**
    364  * drm_atomic_helper_plane_destroy_state - default state destroy hook
    365  * @plane: drm plane
    366  * @state: plane state object to release
    367  *
    368  * Default plane state destroy hook for drivers which don't have their own
    369  * subclassed plane state structure.
    370  */
    371 void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
    372 					   struct drm_plane_state *state)
    373 {
    374 	__drm_atomic_helper_plane_destroy_state(state);
    375 	kfree(state);
    376 }
    377 EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
    378 
    379 /**
    380  * __drm_atomic_helper_connector_state_reset - reset the connector state
    381  * @conn_state: atomic connector state, must not be NULL
    382  * @connector: connectotr object, must not be NULL
    383  *
    384  * Initializes the newly allocated @conn_state with default
    385  * values. This is useful for drivers that subclass the connector state.
    386  */
    387 void
    388 __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state,
    389 					  struct drm_connector *connector)
    390 {
    391 	conn_state->connector = connector;
    392 }
    393 EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset);
    394 
    395 /**
    396  * __drm_atomic_helper_connector_reset - reset state on connector
    397  * @connector: drm connector
    398  * @conn_state: connector state to assign
    399  *
    400  * Initializes the newly allocated @conn_state and assigns it to
    401  * the &drm_connector->state pointer of @connector, usually required when
    402  * initializing the drivers or when called from the &drm_connector_funcs.reset
    403  * hook.
    404  *
    405  * This is useful for drivers that subclass the connector state.
    406  */
    407 void
    408 __drm_atomic_helper_connector_reset(struct drm_connector *connector,
    409 				    struct drm_connector_state *conn_state)
    410 {
    411 	if (conn_state)
    412 		__drm_atomic_helper_connector_state_reset(conn_state, connector);
    413 
    414 	connector->state = conn_state;
    415 }
    416 EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
    417 
    418 /**
    419  * drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
    420  * @connector: drm connector
    421  *
    422  * Resets the atomic state for @connector by freeing the state pointer (which
    423  * might be NULL, e.g. at driver load time) and allocating a new empty state
    424  * object.
    425  */
    426 void drm_atomic_helper_connector_reset(struct drm_connector *connector)
    427 {
    428 	struct drm_connector_state *conn_state =
    429 		kzalloc(sizeof(*conn_state), GFP_KERNEL);
    430 
    431 	if (connector->state)
    432 		__drm_atomic_helper_connector_destroy_state(connector->state);
    433 
    434 	kfree(connector->state);
    435 	__drm_atomic_helper_connector_reset(connector, conn_state);
    436 }
    437 EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
    438 
    439 /**
    440  * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
    441  * @connector: DRM connector
    442  *
    443  * Resets the TV-related properties attached to a connector.
    444  */
    445 void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
    446 {
    447 	struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
    448 	struct drm_connector_state *state = connector->state;
    449 
    450 	state->tv.margins.left = cmdline->tv_margins.left;
    451 	state->tv.margins.right = cmdline->tv_margins.right;
    452 	state->tv.margins.top = cmdline->tv_margins.top;
    453 	state->tv.margins.bottom = cmdline->tv_margins.bottom;
    454 }
    455 EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
    456 
    457 /**
    458  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
    459  * @connector: connector object
    460  * @state: atomic connector state
    461  *
    462  * Copies atomic state from a connector's current state. This is useful for
    463  * drivers that subclass the connector state.
    464  */
    465 void
    466 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
    467 					    struct drm_connector_state *state)
    468 {
    469 	memcpy(state, connector->state, sizeof(*state));
    470 	if (state->crtc)
    471 		drm_connector_get(connector);
    472 	state->commit = NULL;
    473 
    474 	if (state->hdr_output_metadata)
    475 		drm_property_blob_get(state->hdr_output_metadata);
    476 
    477 	/* Don't copy over a writeback job, they are used only once */
    478 	state->writeback_job = NULL;
    479 }
    480 EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
    481 
    482 /**
    483  * drm_atomic_helper_connector_duplicate_state - default state duplicate hook
    484  * @connector: drm connector
    485  *
    486  * Default connector state duplicate hook for drivers which don't have their own
    487  * subclassed connector state structure.
    488  */
    489 struct drm_connector_state *
    490 drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
    491 {
    492 	struct drm_connector_state *state;
    493 
    494 	if (WARN_ON(!connector->state))
    495 		return NULL;
    496 
    497 	state = kmalloc(sizeof(*state), GFP_KERNEL);
    498 	if (state)
    499 		__drm_atomic_helper_connector_duplicate_state(connector, state);
    500 
    501 	return state;
    502 }
    503 EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
    504 
    505 /**
    506  * __drm_atomic_helper_connector_destroy_state - release connector state
    507  * @state: connector state object to release
    508  *
    509  * Releases all resources stored in the connector state without actually
    510  * freeing the memory of the connector state. This is useful for drivers that
    511  * subclass the connector state.
    512  */
    513 void
    514 __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
    515 {
    516 	if (state->crtc)
    517 		drm_connector_put(state->connector);
    518 
    519 	if (state->commit)
    520 		drm_crtc_commit_put(state->commit);
    521 
    522 	if (state->writeback_job)
    523 		drm_writeback_cleanup_job(state->writeback_job);
    524 
    525 	drm_property_blob_put(state->hdr_output_metadata);
    526 }
    527 EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
    528 
    529 /**
    530  * drm_atomic_helper_connector_destroy_state - default state destroy hook
    531  * @connector: drm connector
    532  * @state: connector state object to release
    533  *
    534  * Default connector state destroy hook for drivers which don't have their own
    535  * subclassed connector state structure.
    536  */
    537 void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
    538 					  struct drm_connector_state *state)
    539 {
    540 	__drm_atomic_helper_connector_destroy_state(state);
    541 	kfree(state);
    542 }
    543 EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
    544 
    545 /**
    546  * __drm_atomic_helper_private_duplicate_state - copy atomic private state
    547  * @obj: CRTC object
    548  * @state: new private object state
    549  *
    550  * Copies atomic state from a private objects's current state and resets inferred values.
    551  * This is useful for drivers that subclass the private state.
    552  */
    553 void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
    554 						     struct drm_private_state *state)
    555 {
    556 	memcpy(state, obj->state, sizeof(*state));
    557 }
    558 EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state);
    559