linux/drivers/gpu/drm/drm_atomic.c

/*
 * Copyright (C) 2014 Red Hat
 * Copyright (C) 2014 Intel Corp.
 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 * Rob Clark <[email protected]>
 * Daniel Vetter <[email protected]>
 */


#include <linux/sync_file.h>

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_blend.h>
#include <drm/drm_bridge.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_mode.h>
#include <drm/drm_print.h>
#include <drm/drm_writeback.h>

#include "drm_crtc_internal.h"
#include "drm_internal.h"

void __drm_crtc_commit_free(struct kref *kref)
{}
EXPORT_SYMBOL();

/**
 * drm_crtc_commit_wait - Waits for a commit to complete
 * @commit: &drm_crtc_commit to wait for
 *
 * Waits for a given &drm_crtc_commit to be programmed into the
 * hardware and flipped to.
 *
 * Returns:
 * 0 on success, a negative error code otherwise.
 */
int drm_crtc_commit_wait(struct drm_crtc_commit *commit)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_state_default_release -
 * release memory initialized by drm_atomic_state_init
 * @state: atomic state
 *
 * Free all the memory allocated by drm_atomic_state_init.
 * This should only be used by drivers which are still subclassing
 * &drm_atomic_state and haven't switched to &drm_private_state yet.
 */
void drm_atomic_state_default_release(struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_state_init - init new atomic state
 * @dev: DRM device
 * @state: atomic state
 *
 * Default implementation for filling in a new atomic state.
 * This should only be used by drivers which are still subclassing
 * &drm_atomic_state and haven't switched to &drm_private_state yet.
 */
int
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_state_alloc - allocate atomic state
 * @dev: DRM device
 *
 * This allocates an empty atomic state to track updates.
 */
struct drm_atomic_state *
drm_atomic_state_alloc(struct drm_device *dev)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_state_default_clear - clear base atomic state
 * @state: atomic state
 *
 * Default implementation for clearing atomic state.
 * This should only be used by drivers which are still subclassing
 * &drm_atomic_state and haven't switched to &drm_private_state yet.
 */
void drm_atomic_state_default_clear(struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_state_clear - clear state object
 * @state: atomic state
 *
 * When the w/w mutex algorithm detects a deadlock we need to back off and drop
 * all locks. So someone else could sneak in and change the current modeset
 * configuration. Which means that all the state assembled in @state is no
 * longer an atomic update to the current state, but to some arbitrary earlier
 * state. Which could break assumptions the driver's
 * &drm_mode_config_funcs.atomic_check likely relies on.
 *
 * Hence we must clear all cached state and completely start over, using this
 * function.
 */
void drm_atomic_state_clear(struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

/**
 * __drm_atomic_state_free - free all memory for an atomic state
 * @ref: This atomic state to deallocate
 *
 * This frees all memory associated with an atomic state, including all the
 * per-object state for planes, CRTCs and connectors.
 */
void __drm_atomic_state_free(struct kref *ref)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_crtc_state - get CRTC state
 * @state: global atomic state object
 * @crtc: CRTC to get state object for
 *
 * This function returns the CRTC state for the given CRTC, allocating it if
 * needed. It will also grab the relevant CRTC lock to make sure that the state
 * is consistent.
 *
 * WARNING: Drivers may only add new CRTC states to a @state if
 * drm_atomic_state.allow_modeset is set, or if it's a driver-internal commit
 * not created by userspace through an IOCTL call.
 *
 * Returns:
 * Either the allocated state or the error code encoded into the pointer. When
 * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
 * entire atomic sequence must be restarted. All other errors are fatal.
 */
struct drm_crtc_state *
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
			  struct drm_crtc *crtc)
{}
EXPORT_SYMBOL();

static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state,
				 const struct drm_crtc_state *new_crtc_state)
{}

static void drm_atomic_crtc_print_state(struct drm_printer *p,
		const struct drm_crtc_state *state)
{}

static int drm_atomic_connector_check(struct drm_connector *connector,
		struct drm_connector_state *state)
{}

/**
 * drm_atomic_get_plane_state - get plane state
 * @state: global atomic state object
 * @plane: plane to get state object for
 *
 * This function returns the plane state for the given plane, allocating it if
 * needed. It will also grab the relevant plane lock to make sure that the state
 * is consistent.
 *
 * Returns:
 * Either the allocated state or the error code encoded into the pointer. When
 * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
 * entire atomic sequence must be restarted. All other errors are fatal.
 */
struct drm_plane_state *
drm_atomic_get_plane_state(struct drm_atomic_state *state,
			  struct drm_plane *plane)
{}
EXPORT_SYMBOL();

static bool
plane_switching_crtc(const struct drm_plane_state *old_plane_state,
		     const struct drm_plane_state *new_plane_state)
{}

/**
 * drm_atomic_plane_check - check plane state
 * @old_plane_state: old plane state to check
 * @new_plane_state: new plane state to check
 *
 * Provides core sanity checks for plane state.
 *
 * RETURNS:
 * Zero on success, error code on failure
 */
static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
				  const struct drm_plane_state *new_plane_state)
{}

static void drm_atomic_plane_print_state(struct drm_printer *p,
		const struct drm_plane_state *state)
{}

/**
 * DOC: handling driver private state
 *
 * Very often the DRM objects exposed to userspace in the atomic modeset api
 * (&drm_connector, &drm_crtc and &drm_plane) do not map neatly to the
 * underlying hardware. Especially for any kind of shared resources (e.g. shared
 * clocks, scaler units, bandwidth and fifo limits shared among a group of
 * planes or CRTCs, and so on) it makes sense to model these as independent
 * objects. Drivers then need to do similar state tracking and commit ordering for
 * such private (since not exposed to userspace) objects as the atomic core and
 * helpers already provide for connectors, planes and CRTCs.
 *
 * To make this easier on drivers the atomic core provides some support to track
 * driver private state objects using struct &drm_private_obj, with the
 * associated state struct &drm_private_state.
 *
 * Similar to userspace-exposed objects, private state structures can be
 * acquired by calling drm_atomic_get_private_obj_state(). This also takes care
 * of locking, hence drivers should not have a need to call drm_modeset_lock()
 * directly. Sequence of the actual hardware state commit is not handled,
 * drivers might need to keep track of struct drm_crtc_commit within subclassed
 * structure of &drm_private_state as necessary, e.g. similar to
 * &drm_plane_state.commit. See also &drm_atomic_state.fake_commit.
 *
 * All private state structures contained in a &drm_atomic_state update can be
 * iterated using for_each_oldnew_private_obj_in_state(),
 * for_each_new_private_obj_in_state() and for_each_old_private_obj_in_state().
 * Drivers are recommended to wrap these for each type of driver private state
 * object they have, filtering on &drm_private_obj.funcs using for_each_if(), at
 * least if they want to iterate over all objects of a given type.
 *
 * An earlier way to handle driver private state was by subclassing struct
 * &drm_atomic_state. But since that encourages non-standard ways to implement
 * the check/commit split atomic requires (by using e.g. "check and rollback or
 * commit instead" of "duplicate state, check, then either commit or release
 * duplicated state) it is deprecated in favour of using &drm_private_state.
 */

/**
 * drm_atomic_private_obj_init - initialize private object
 * @dev: DRM device this object will be attached to
 * @obj: private object
 * @state: initial private object state
 * @funcs: pointer to the struct of function pointers that identify the object
 * type
 *
 * Initialize the private object, which can be embedded into any
 * driver private object that needs its own atomic state.
 */
void
drm_atomic_private_obj_init(struct drm_device *dev,
			    struct drm_private_obj *obj,
			    struct drm_private_state *state,
			    const struct drm_private_state_funcs *funcs)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_private_obj_fini - finalize private object
 * @obj: private object
 *
 * Finalize the private object.
 */
void
drm_atomic_private_obj_fini(struct drm_private_obj *obj)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_private_obj_state - get private object state
 * @state: global atomic state
 * @obj: private object to get the state for
 *
 * This function returns the private object state for the given private object,
 * allocating the state if needed. It will also grab the relevant private
 * object lock to make sure that the state is consistent.
 *
 * RETURNS:
 * Either the allocated state or the error code encoded into a pointer.
 */
struct drm_private_state *
drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
				 struct drm_private_obj *obj)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_old_private_obj_state
 * @state: global atomic state object
 * @obj: private_obj to grab
 *
 * This function returns the old private object state for the given private_obj,
 * or NULL if the private_obj is not part of the global atomic state.
 */
struct drm_private_state *
drm_atomic_get_old_private_obj_state(const struct drm_atomic_state *state,
				     struct drm_private_obj *obj)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_new_private_obj_state
 * @state: global atomic state object
 * @obj: private_obj to grab
 *
 * This function returns the new private object state for the given private_obj,
 * or NULL if the private_obj is not part of the global atomic state.
 */
struct drm_private_state *
drm_atomic_get_new_private_obj_state(const struct drm_atomic_state *state,
				     struct drm_private_obj *obj)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_old_connector_for_encoder - Get old connector for an encoder
 * @state: Atomic state
 * @encoder: The encoder to fetch the connector state for
 *
 * This function finds and returns the connector that was connected to @encoder
 * as specified by the @state.
 *
 * If there is no connector in @state which previously had @encoder connected to
 * it, this function will return NULL. While this may seem like an invalid use
 * case, it is sometimes useful to differentiate commits which had no prior
 * connectors attached to @encoder vs ones that did (and to inspect their
 * state). This is especially true in enable hooks because the pipeline has
 * changed.
 *
 * Returns: The old connector connected to @encoder, or NULL if the encoder is
 * not connected.
 */
struct drm_connector *
drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state *state,
					 struct drm_encoder *encoder)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_new_connector_for_encoder - Get new connector for an encoder
 * @state: Atomic state
 * @encoder: The encoder to fetch the connector state for
 *
 * This function finds and returns the connector that will be connected to
 * @encoder as specified by the @state.
 *
 * If there is no connector in @state which will have @encoder connected to it,
 * this function will return NULL. While this may seem like an invalid use case,
 * it is sometimes useful to differentiate commits which have no connectors
 * attached to @encoder vs ones that do (and to inspect their state). This is
 * especially true in disable hooks because the pipeline will change.
 *
 * Returns: The new connector connected to @encoder, or NULL if the encoder is
 * not connected.
 */
struct drm_connector *
drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state,
					 struct drm_encoder *encoder)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_old_crtc_for_encoder - Get old crtc for an encoder
 * @state: Atomic state
 * @encoder: The encoder to fetch the crtc state for
 *
 * This function finds and returns the crtc that was connected to @encoder
 * as specified by the @state.
 *
 * Returns: The old crtc connected to @encoder, or NULL if the encoder is
 * not connected.
 */
struct drm_crtc *
drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state,
				    struct drm_encoder *encoder)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_new_crtc_for_encoder - Get new crtc for an encoder
 * @state: Atomic state
 * @encoder: The encoder to fetch the crtc state for
 *
 * This function finds and returns the crtc that will be connected to @encoder
 * as specified by the @state.
 *
 * Returns: The new crtc connected to @encoder, or NULL if the encoder is
 * not connected.
 */
struct drm_crtc *
drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state,
				    struct drm_encoder *encoder)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_connector_state - get connector state
 * @state: global atomic state object
 * @connector: connector to get state object for
 *
 * This function returns the connector state for the given connector,
 * allocating it if needed. It will also grab the relevant connector lock to
 * make sure that the state is consistent.
 *
 * Returns:
 * Either the allocated state or the error code encoded into the pointer. When
 * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
 * entire atomic sequence must be restarted. All other errors are fatal.
 */
struct drm_connector_state *
drm_atomic_get_connector_state(struct drm_atomic_state *state,
			  struct drm_connector *connector)
{}
EXPORT_SYMBOL();

static void drm_atomic_connector_print_state(struct drm_printer *p,
		const struct drm_connector_state *state)
{}

/**
 * drm_atomic_get_bridge_state - get bridge state
 * @state: global atomic state object
 * @bridge: bridge to get state object for
 *
 * This function returns the bridge state for the given bridge, allocating it
 * if needed. It will also grab the relevant bridge lock to make sure that the
 * state is consistent.
 *
 * Returns:
 * Either the allocated state or the error code encoded into the pointer. When
 * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
 * entire atomic sequence must be restarted.
 */
struct drm_bridge_state *
drm_atomic_get_bridge_state(struct drm_atomic_state *state,
			    struct drm_bridge *bridge)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_old_bridge_state - get old bridge state, if it exists
 * @state: global atomic state object
 * @bridge: bridge to grab
 *
 * This function returns the old bridge state for the given bridge, or NULL if
 * the bridge is not part of the global atomic state.
 */
struct drm_bridge_state *
drm_atomic_get_old_bridge_state(const struct drm_atomic_state *state,
				struct drm_bridge *bridge)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_get_new_bridge_state - get new bridge state, if it exists
 * @state: global atomic state object
 * @bridge: bridge to grab
 *
 * This function returns the new bridge state for the given bridge, or NULL if
 * the bridge is not part of the global atomic state.
 */
struct drm_bridge_state *
drm_atomic_get_new_bridge_state(const struct drm_atomic_state *state,
				struct drm_bridge *bridge)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_add_encoder_bridges - add bridges attached to an encoder
 * @state: atomic state
 * @encoder: DRM encoder
 *
 * This function adds all bridges attached to @encoder. This is needed to add
 * bridge states to @state and make them available when
 * &drm_bridge_funcs.atomic_check(), &drm_bridge_funcs.atomic_pre_enable(),
 * &drm_bridge_funcs.atomic_enable(),
 * &drm_bridge_funcs.atomic_disable_post_disable() are called.
 *
 * Returns:
 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
 * then the w/w mutex code has detected a deadlock and the entire atomic
 * sequence must be restarted. All other errors are fatal.
 */
int
drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
			       struct drm_encoder *encoder)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_add_affected_connectors - add connectors for CRTC
 * @state: atomic state
 * @crtc: DRM CRTC
 *
 * This function walks the current configuration and adds all connectors
 * currently using @crtc to the atomic configuration @state. Note that this
 * function must acquire the connection mutex. This can potentially cause
 * unneeded serialization if the update is just for the planes on one CRTC. Hence
 * drivers and helpers should only call this when really needed (e.g. when a
 * full modeset needs to happen due to some change).
 *
 * Returns:
 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
 * then the w/w mutex code has detected a deadlock and the entire atomic
 * sequence must be restarted. All other errors are fatal.
 */
int
drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
				   struct drm_crtc *crtc)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_add_affected_planes - add planes for CRTC
 * @state: atomic state
 * @crtc: DRM CRTC
 *
 * This function walks the current configuration and adds all planes
 * currently used by @crtc to the atomic configuration @state. This is useful
 * when an atomic commit also needs to check all currently enabled plane on
 * @crtc, e.g. when changing the mode. It's also useful when re-enabling a CRTC
 * to avoid special code to force-enable all planes.
 *
 * Since acquiring a plane state will always also acquire the w/w mutex of the
 * current CRTC for that plane (if there is any) adding all the plane states for
 * a CRTC will not reduce parallelism of atomic updates.
 *
 * Returns:
 * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
 * then the w/w mutex code has detected a deadlock and the entire atomic
 * sequence must be restarted. All other errors are fatal.
 */
int
drm_atomic_add_affected_planes(struct drm_atomic_state *state,
			       struct drm_crtc *crtc)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_check_only - check whether a given config would work
 * @state: atomic configuration to check
 *
 * Note that this function can return -EDEADLK if the driver needed to acquire
 * more locks but encountered a deadlock. The caller must then do the usual w/w
 * backoff dance and restart. All other errors are fatal.
 *
 * Returns:
 * 0 on success, negative error code on failure.
 */
int drm_atomic_check_only(struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_commit - commit configuration atomically
 * @state: atomic configuration to check
 *
 * Note that this function can return -EDEADLK if the driver needed to acquire
 * more locks but encountered a deadlock. The caller must then do the usual w/w
 * backoff dance and restart. All other errors are fatal.
 *
 * This function will take its own reference on @state.
 * Callers should always release their reference with drm_atomic_state_put().
 *
 * Returns:
 * 0 on success, negative error code on failure.
 */
int drm_atomic_commit(struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

/**
 * drm_atomic_nonblocking_commit - atomic nonblocking commit
 * @state: atomic configuration to check
 *
 * Note that this function can return -EDEADLK if the driver needed to acquire
 * more locks but encountered a deadlock. The caller must then do the usual w/w
 * backoff dance and restart. All other errors are fatal.
 *
 * This function will take its own reference on @state.
 * Callers should always release their reference with drm_atomic_state_put().
 *
 * Returns:
 * 0 on success, negative error code on failure.
 */
int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

/* just used from drm-client and atomic-helper: */
int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
				      struct drm_plane_state *plane_state)
{}
EXPORT_SYMBOL();

static int update_output_state(struct drm_atomic_state *state,
			       struct drm_mode_set *set)
{}

/* just used from drm-client and atomic-helper: */
int __drm_atomic_helper_set_config(struct drm_mode_set *set,
				   struct drm_atomic_state *state)
{}
EXPORT_SYMBOL();

static void drm_atomic_private_obj_print_state(struct drm_printer *p,
					       const struct drm_private_state *state)
{}

/**
 * drm_atomic_print_new_state - prints drm atomic state
 * @state: atomic configuration to check
 * @p: drm printer
 *
 * This functions prints the drm atomic state snapshot using the drm printer
 * which is passed to it. This snapshot can be used for debugging purposes.
 *
 * Note that this function looks into the new state objects and hence its not
 * safe to be used after the call to drm_atomic_helper_commit_hw_done().
 */
void drm_atomic_print_new_state(const struct drm_atomic_state *state,
		struct drm_printer *p)
{}
EXPORT_SYMBOL();

static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
			     bool take_locks)
{}

/**
 * drm_state_dump - dump entire device atomic state
 * @dev: the drm device
 * @p: where to print the state to
 *
 * Just for debugging.  Drivers might want an option to dump state
 * to dmesg in case of error irq's.  (Hint, you probably want to
 * ratelimit this!)
 *
 * The caller must wrap this drm_modeset_lock_all_ctx() and
 * drm_modeset_drop_locks(). If this is called from error irq handler, it should
 * not be enabled by default - if you are debugging errors you might
 * not care that this is racey, but calling this without all modeset locks held
 * is inherently unsafe.
 */
void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_DEBUG_FS
static int drm_state_info(struct seq_file *m, void *data)
{}

/* any use in debugfs files to dump individual planes/crtc/etc? */
static const struct drm_debugfs_info drm_atomic_debugfs_list[] =;

void drm_atomic_debugfs_init(struct drm_device *dev)
{}
#endif