2223 lines · 70.6 KB · C
RawDownload
/* * 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 <robdclark@gmail.com> * Daniel Vetter <daniel.vetter@ffwll.ch> */ #include <linux/export.h>#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/drm_colorop.h> #include "drm_crtc_internal.h"#include "drm_internal.h" /** * DOC: state lifetime * * &drm_atomic_commit represents an update to modeset pipeline state. * It's a transient object that holds a state update as a collection of * pointers to individual objects' states. &drm_atomic_commit has a much * shorter lifetime than the objects' states, since it's only allocated * while preparing, checking or committing the update, while object * states are allocated when preparing the update and kept alive as long * as they are active in the device. * * Their respective lifetimes are: * * - at driver initialization time, the driver calls *   drm_mode_config_create_initial_state() to allocate an initial, *   pristine, state for each object and stores it in the objects state *   pointer. Historically, this was one of drm_mode_config_reset() job, *   so one might still encounter it in a driver. * * - When resuming from suspend, drm_mode_config_reset() resets the *   software and hardware state to a known default and stores it in the *   object's state pointer. Not all objects are affected by *   drm_mode_config_reset() though. * * - whenever a new update is needed: * *   + drm_atomic_commit_alloc() allocates a new &drm_atomic_commit *     instance. * *   + The code triggering the commit (ioctl, client modeset, *     drm_atomic_helper_reset_crtc(), etc.) copies the current active *     state of all entities affected by the update into this new *     &drm_atomic_commit using drm_atomic_get_plane_state(), *     drm_atomic_get_crtc_state(), drm_atomic_get_connector_state(), or *     drm_atomic_get_private_obj_state(). This new state can then be *     modified. * *     At that point, &drm_atomic_commit stores three state pointers for *     any affected entity: the "old" and "new" states, and *     state_to_destroy. The old state is the state currently active in *     the hardware, which is either the one initialized by reset() or a *     newer one if a commit has been made. The new state is the state *     we just allocated and we might eventually commit to the hardware. *     The state_to_destroy points to the state we'll eventually have to *     free when the drm_atomic_commit will be destroyed, and points to *     the new state for now since the old state is still the active *     state. * *   + After the calling code populated the commit with the entities *     states, it updates the new states with the new values we need to *     commit. The new commit instance is now ready. * *   + Then we have two branches depending on the calling code intent: * *     - If the calling code only wants to check that the commit would *       work (for example because of the DRM_MODE_ATOMIC_TEST_ONLY *       flag). It calls drm_atomic_check_only(), which in turn checks *       all these states by invoking atomic_check on all affected *       pipeline stages. * *     - If the calling code actually wants to trigger a commit, it *       calls drm_atomic_commit(). The first stage is the check *       mentioned above, and if the check is successful, it performs *       the commit. Part of the commit is a call to *       drm_atomic_helper_swap_state() which turns the new states into *       the active states. After swapping states, each object's state *       pointer now refers to the formerly new state. The *       state_to_destroy now refers to the formerly old state. * *   + Once done, and when the last reference to our &drm_atomic_commit *     is given up through drm_atomic_commit_put(), it calls *     __drm_atomic_commit_free(). In turn, __drm_atomic_commit_free() *     calls drm_atomic_commit_clear() that will free all *     state_to_destroy (ie. old states), and it finally frees *     &drm_atomic_commit instance. * *   + Now, we don't have any active &drm_atomic_commit anymore, and *     only the entity active states remain allocated. */ void __drm_crtc_commit_free(struct kref *kref){	struct drm_crtc_commit *commit =		container_of(kref, struct drm_crtc_commit, ref); 	kfree(commit);}EXPORT_SYMBOL(__drm_crtc_commit_free); /** * 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){	unsigned long timeout = 10 * HZ;	int ret; 	if (!commit)		return 0; 	ret = wait_for_completion_timeout(&commit->hw_done, timeout);	if (!ret) {		drm_err(commit->crtc->dev, "hw_done timed out\n");		return -ETIMEDOUT;	} 	/*	 * Currently no support for overwriting flips, hence	 * stall for previous one to execute completely.	 */	ret = wait_for_completion_timeout(&commit->flip_done, timeout);	if (!ret) {		drm_err(commit->crtc->dev, "flip_done timed out\n");		return -ETIMEDOUT;	} 	return 0;}EXPORT_SYMBOL(drm_crtc_commit_wait); /** * drm_atomic_commit_default_release - * release memory initialized by drm_atomic_commit_init * @state: atomic state * * Free all the memory allocated by drm_atomic_commit_init. * This should only be used by drivers which are still subclassing * &drm_atomic_commit and haven't switched to &drm_private_state yet. */void drm_atomic_commit_default_release(struct drm_atomic_commit *state){	kfree(state->connectors);	kfree(state->crtcs);	kfree(state->planes);	kfree(state->colorops);	kfree(state->private_objs);}EXPORT_SYMBOL(drm_atomic_commit_default_release); /** * drm_atomic_commit_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_commit and haven't switched to &drm_private_state yet. */intdrm_atomic_commit_init(struct drm_device *dev, struct drm_atomic_commit *state){	kref_init(&state->ref); 	/* TODO legacy paths should maybe do a better job about	 * setting this appropriately?	 */	state->allow_modeset = true; 	state->crtcs = kzalloc_objs(*state->crtcs, dev->mode_config.num_crtc);	if (!state->crtcs)		goto fail;	state->planes = kzalloc_objs(*state->planes,				     dev->mode_config.num_total_plane);	if (!state->planes)		goto fail;	state->colorops = kzalloc_objs(*state->colorops,				       dev->mode_config.num_colorop);	if (!state->colorops)		goto fail; 	/*	 * Because drm_atomic_commit can be committed asynchronously we need our	 * own reference and cannot rely on the on implied by drm_file in the	 * ioctl call.	 */	drm_dev_get(dev);	state->dev = dev; 	drm_dbg_atomic(dev, "Allocated atomic state %p\n", state); 	return 0;fail:	drm_atomic_commit_default_release(state);	return -ENOMEM;}EXPORT_SYMBOL(drm_atomic_commit_init); /** * drm_atomic_commit_alloc - allocate atomic state * @dev: DRM device * * This allocates an empty atomic state to track updates. */struct drm_atomic_commit *drm_atomic_commit_alloc(struct drm_device *dev){	struct drm_mode_config *config = &dev->mode_config; 	if (!config->funcs->atomic_state_alloc) {		struct drm_atomic_commit *state; 		state = kzalloc_obj(*state);		if (!state)			return NULL;		if (drm_atomic_commit_init(dev, state) < 0) {			kfree(state);			return NULL;		}		return state;	} 	return config->funcs->atomic_state_alloc(dev);}EXPORT_SYMBOL(drm_atomic_commit_alloc); /** * drm_atomic_commit_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_commit and haven't switched to &drm_private_state yet. */void drm_atomic_commit_default_clear(struct drm_atomic_commit *state){	struct drm_device *dev = state->dev;	struct drm_mode_config *config = &dev->mode_config;	int i; 	drm_dbg_atomic(dev, "Clearing atomic state %p\n", state); 	state->checked = false; 	for (i = 0; i < state->num_connector; i++) {		struct drm_connector *connector = state->connectors[i].ptr; 		if (!connector)			continue; 		connector->funcs->atomic_destroy_state(connector,						       state->connectors[i].state_to_destroy);		state->connectors[i].ptr = NULL;		state->connectors[i].state_to_destroy = NULL;		state->connectors[i].old_state = NULL;		state->connectors[i].new_state = NULL;		drm_connector_put(connector);	} 	for (i = 0; i < config->num_crtc; i++) {		struct drm_crtc *crtc = state->crtcs[i].ptr; 		if (!crtc)			continue; 		crtc->funcs->atomic_destroy_state(crtc,						  state->crtcs[i].state_to_destroy); 		state->crtcs[i].ptr = NULL;		state->crtcs[i].state_to_destroy = NULL;		state->crtcs[i].old_state = NULL;		state->crtcs[i].new_state = NULL; 		if (state->crtcs[i].commit) {			drm_crtc_commit_put(state->crtcs[i].commit);			state->crtcs[i].commit = NULL;		}	} 	for (i = 0; i < config->num_total_plane; i++) {		struct drm_plane *plane = state->planes[i].ptr; 		if (!plane)			continue; 		plane->funcs->atomic_destroy_state(plane,						   state->planes[i].state_to_destroy);		state->planes[i].ptr = NULL;		state->planes[i].state_to_destroy = NULL;		state->planes[i].old_state = NULL;		state->planes[i].new_state = NULL;	} 	for (i = 0; i < config->num_colorop; i++) {		struct drm_colorop *colorop = state->colorops[i].ptr; 		if (!colorop)			continue; 		drm_colorop_atomic_destroy_state(colorop,						 state->colorops[i].state);		state->colorops[i].ptr = NULL;		state->colorops[i].state = NULL;		state->colorops[i].old_state = NULL;		state->colorops[i].new_state = NULL;	} 	for (i = 0; i < state->num_private_objs; i++) {		struct drm_private_obj *obj = state->private_objs[i].ptr; 		obj->funcs->atomic_destroy_state(obj,						 state->private_objs[i].state_to_destroy);		state->private_objs[i].ptr = NULL;		state->private_objs[i].state_to_destroy = NULL;		state->private_objs[i].old_state = NULL;		state->private_objs[i].new_state = NULL;	}	state->num_private_objs = 0; 	if (state->fake_commit) {		drm_crtc_commit_put(state->fake_commit);		state->fake_commit = NULL;	}}EXPORT_SYMBOL(drm_atomic_commit_default_clear); /** * drm_atomic_commit_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_commit_clear(struct drm_atomic_commit *state){	struct drm_device *dev = state->dev;	struct drm_mode_config *config = &dev->mode_config; 	if (config->funcs->atomic_state_clear)		config->funcs->atomic_state_clear(state);	else		drm_atomic_commit_default_clear(state);}EXPORT_SYMBOL(drm_atomic_commit_clear); /** * __drm_atomic_commit_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_commit_free(struct kref *ref){	struct drm_atomic_commit *state = container_of(ref, typeof(*state), ref);	struct drm_device *dev = state->dev;	struct drm_mode_config *config = &dev->mode_config; 	drm_atomic_commit_clear(state); 	drm_dbg_atomic(state->dev, "Freeing atomic state %p\n", state); 	if (config->funcs->atomic_state_free) {		config->funcs->atomic_state_free(state);	} else {		drm_atomic_commit_default_release(state);		kfree(state);	} 	drm_dev_put(dev);}EXPORT_SYMBOL(__drm_atomic_commit_free); /** * 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_commit.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_commit *state,			  struct drm_crtc *crtc){	int ret, index = drm_crtc_index(crtc);	struct drm_crtc_state *crtc_state; 	WARN_ON(!state->acquire_ctx);	drm_WARN_ON(state->dev, state->checked); 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);	if (crtc_state)		return crtc_state; 	ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx);	if (ret)		return ERR_PTR(ret); 	crtc_state = crtc->funcs->atomic_duplicate_state(crtc);	if (!crtc_state)		return ERR_PTR(-ENOMEM); 	state->crtcs[index].state_to_destroy = crtc_state;	state->crtcs[index].old_state = crtc->state;	state->crtcs[index].new_state = crtc_state;	state->crtcs[index].ptr = crtc;	crtc_state->state = state; 	drm_dbg_atomic(state->dev, "Added [CRTC:%d:%s] %p state to %p\n",		       crtc->base.id, crtc->name, crtc_state, state); 	return crtc_state;}EXPORT_SYMBOL(drm_atomic_get_crtc_state); static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state,				 const struct drm_crtc_state *new_crtc_state){	struct drm_crtc *crtc = new_crtc_state->crtc; 	/* NOTE: we explicitly don't enforce constraints such as primary	 * layer covering entire screen, since that is something we want	 * to allow (on hw that supports it).  For hw that does not, it	 * should be checked in driver's crtc->atomic_check() vfunc.	 *	 * TODO: Add generic modeset state checks once we support those.	 */ 	if (new_crtc_state->active && !new_crtc_state->enable) {		drm_dbg_atomic(crtc->dev,			       "[CRTC:%d:%s] active without enabled\n",			       crtc->base.id, crtc->name);		return -EINVAL;	} 	/* The state->enable vs. state->mode_blob checks can be WARN_ON,	 * as this is a kernel-internal detail that userspace should never

Lines 1–500 of 2223.