xref: /linux/drivers/gpu/drm/drm_atomic.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1cc4ceb48SDaniel Vetter /*
2cc4ceb48SDaniel Vetter  * Copyright (C) 2014 Red Hat
3cc4ceb48SDaniel Vetter  * Copyright (C) 2014 Intel Corp.
4a4324a7aSAbhinav Kumar  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
5cc4ceb48SDaniel Vetter  *
6cc4ceb48SDaniel Vetter  * Permission is hereby granted, free of charge, to any person obtaining a
7cc4ceb48SDaniel Vetter  * copy of this software and associated documentation files (the "Software"),
8cc4ceb48SDaniel Vetter  * to deal in the Software without restriction, including without limitation
9cc4ceb48SDaniel Vetter  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10cc4ceb48SDaniel Vetter  * and/or sell copies of the Software, and to permit persons to whom the
11cc4ceb48SDaniel Vetter  * Software is furnished to do so, subject to the following conditions:
12cc4ceb48SDaniel Vetter  *
13cc4ceb48SDaniel Vetter  * The above copyright notice and this permission notice shall be included in
14cc4ceb48SDaniel Vetter  * all copies or substantial portions of the Software.
15cc4ceb48SDaniel Vetter  *
16cc4ceb48SDaniel Vetter  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17cc4ceb48SDaniel Vetter  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18cc4ceb48SDaniel Vetter  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19cc4ceb48SDaniel Vetter  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20cc4ceb48SDaniel Vetter  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21cc4ceb48SDaniel Vetter  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22cc4ceb48SDaniel Vetter  * OTHER DEALINGS IN THE SOFTWARE.
23cc4ceb48SDaniel Vetter  *
24cc4ceb48SDaniel Vetter  * Authors:
25cc4ceb48SDaniel Vetter  * Rob Clark <robdclark@gmail.com>
26cc4ceb48SDaniel Vetter  * Daniel Vetter <daniel.vetter@ffwll.ch>
27cc4ceb48SDaniel Vetter  */
28cc4ceb48SDaniel Vetter 
29cc4ceb48SDaniel Vetter 
300500c04eSSam Ravnborg #include <linux/sync_file.h>
310500c04eSSam Ravnborg 
32cc4ceb48SDaniel Vetter #include <drm/drm_atomic.h>
3372fdb40cSDaniel Vetter #include <drm/drm_atomic_uapi.h>
3490bb087fSVille Syrjälä #include <drm/drm_blend.h>
3575146591SBoris Brezillon #include <drm/drm_bridge.h>
360500c04eSSam Ravnborg #include <drm/drm_debugfs.h>
370500c04eSSam Ravnborg #include <drm/drm_device.h>
380500c04eSSam Ravnborg #include <drm/drm_drv.h>
390500c04eSSam Ravnborg #include <drm/drm_file.h>
400500c04eSSam Ravnborg #include <drm/drm_fourcc.h>
41720cf96dSVille Syrjälä #include <drm/drm_framebuffer.h>
425488dc16SLionel Landwerlin #include <drm/drm_mode.h>
43fceffb32SRob Clark #include <drm/drm_print.h>
44935774cdSBrian Starkey #include <drm/drm_writeback.h>
45cc4ceb48SDaniel Vetter 
46be35f94fSThierry Reding #include "drm_crtc_internal.h"
47f02b604bSNoralf Trønnes #include "drm_internal.h"
48be35f94fSThierry Reding 
__drm_crtc_commit_free(struct kref * kref)49b3ba3f6fSDaniel Vetter void __drm_crtc_commit_free(struct kref *kref)
503b24f7d6SDaniel Vetter {
513b24f7d6SDaniel Vetter 	struct drm_crtc_commit *commit =
523b24f7d6SDaniel Vetter 		container_of(kref, struct drm_crtc_commit, ref);
533b24f7d6SDaniel Vetter 
543b24f7d6SDaniel Vetter 	kfree(commit);
553b24f7d6SDaniel Vetter }
56b3ba3f6fSDaniel Vetter EXPORT_SYMBOL(__drm_crtc_commit_free);
573b24f7d6SDaniel Vetter 
58036ef573SMaarten Lankhorst /**
59b99c2c95SMaxime Ripard  * drm_crtc_commit_wait - Waits for a commit to complete
60b99c2c95SMaxime Ripard  * @commit: &drm_crtc_commit to wait for
61b99c2c95SMaxime Ripard  *
62b99c2c95SMaxime Ripard  * Waits for a given &drm_crtc_commit to be programmed into the
63b99c2c95SMaxime Ripard  * hardware and flipped to.
64b99c2c95SMaxime Ripard  *
65b99c2c95SMaxime Ripard  * Returns:
66b99c2c95SMaxime Ripard  * 0 on success, a negative error code otherwise.
67b99c2c95SMaxime Ripard  */
drm_crtc_commit_wait(struct drm_crtc_commit * commit)68b99c2c95SMaxime Ripard int drm_crtc_commit_wait(struct drm_crtc_commit *commit)
69b99c2c95SMaxime Ripard {
70b99c2c95SMaxime Ripard 	unsigned long timeout = 10 * HZ;
71b99c2c95SMaxime Ripard 	int ret;
72b99c2c95SMaxime Ripard 
73b99c2c95SMaxime Ripard 	if (!commit)
74b99c2c95SMaxime Ripard 		return 0;
75b99c2c95SMaxime Ripard 
76b99c2c95SMaxime Ripard 	ret = wait_for_completion_timeout(&commit->hw_done, timeout);
77b99c2c95SMaxime Ripard 	if (!ret) {
786e22dc35SClaudio Suarez 		drm_err(commit->crtc->dev, "hw_done timed out\n");
79b99c2c95SMaxime Ripard 		return -ETIMEDOUT;
80b99c2c95SMaxime Ripard 	}
81b99c2c95SMaxime Ripard 
82b99c2c95SMaxime Ripard 	/*
83b99c2c95SMaxime Ripard 	 * Currently no support for overwriting flips, hence
84b99c2c95SMaxime Ripard 	 * stall for previous one to execute completely.
85b99c2c95SMaxime Ripard 	 */
86b99c2c95SMaxime Ripard 	ret = wait_for_completion_timeout(&commit->flip_done, timeout);
87b99c2c95SMaxime Ripard 	if (!ret) {
886e22dc35SClaudio Suarez 		drm_err(commit->crtc->dev, "flip_done timed out\n");
89b99c2c95SMaxime Ripard 		return -ETIMEDOUT;
90b99c2c95SMaxime Ripard 	}
91b99c2c95SMaxime Ripard 
92b99c2c95SMaxime Ripard 	return 0;
93b99c2c95SMaxime Ripard }
94b99c2c95SMaxime Ripard EXPORT_SYMBOL(drm_crtc_commit_wait);
95b99c2c95SMaxime Ripard 
96b99c2c95SMaxime Ripard /**
97036ef573SMaarten Lankhorst  * drm_atomic_state_default_release -
98036ef573SMaarten Lankhorst  * release memory initialized by drm_atomic_state_init
99036ef573SMaarten Lankhorst  * @state: atomic state
100036ef573SMaarten Lankhorst  *
101036ef573SMaarten Lankhorst  * Free all the memory allocated by drm_atomic_state_init.
102da6c0596SDaniel Vetter  * This should only be used by drivers which are still subclassing
103da6c0596SDaniel Vetter  * &drm_atomic_state and haven't switched to &drm_private_state yet.
104036ef573SMaarten Lankhorst  */
drm_atomic_state_default_release(struct drm_atomic_state * state)105036ef573SMaarten Lankhorst void drm_atomic_state_default_release(struct drm_atomic_state *state)
106cc4ceb48SDaniel Vetter {
107cc4ceb48SDaniel Vetter 	kfree(state->connectors);
108cc4ceb48SDaniel Vetter 	kfree(state->crtcs);
109cc4ceb48SDaniel Vetter 	kfree(state->planes);
110b430c27aSPandiyan, Dhinakaran 	kfree(state->private_objs);
111cc4ceb48SDaniel Vetter }
112036ef573SMaarten Lankhorst EXPORT_SYMBOL(drm_atomic_state_default_release);
113cc4ceb48SDaniel Vetter 
114cc4ceb48SDaniel Vetter /**
115036ef573SMaarten Lankhorst  * drm_atomic_state_init - init new atomic state
116cc4ceb48SDaniel Vetter  * @dev: DRM device
117036ef573SMaarten Lankhorst  * @state: atomic state
118cc4ceb48SDaniel Vetter  *
119036ef573SMaarten Lankhorst  * Default implementation for filling in a new atomic state.
120da6c0596SDaniel Vetter  * This should only be used by drivers which are still subclassing
121da6c0596SDaniel Vetter  * &drm_atomic_state and haven't switched to &drm_private_state yet.
122cc4ceb48SDaniel Vetter  */
123036ef573SMaarten Lankhorst int
drm_atomic_state_init(struct drm_device * dev,struct drm_atomic_state * state)124036ef573SMaarten Lankhorst drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
125cc4ceb48SDaniel Vetter {
1260853695cSChris Wilson 	kref_init(&state->ref);
1270853695cSChris Wilson 
128d34f20d6SRob Clark 	/* TODO legacy paths should maybe do a better job about
129d34f20d6SRob Clark 	 * setting this appropriately?
130d34f20d6SRob Clark 	 */
131d34f20d6SRob Clark 	state->allow_modeset = true;
132d34f20d6SRob Clark 
133cc4ceb48SDaniel Vetter 	state->crtcs = kcalloc(dev->mode_config.num_crtc,
134cc4ceb48SDaniel Vetter 			       sizeof(*state->crtcs), GFP_KERNEL);
135cc4ceb48SDaniel Vetter 	if (!state->crtcs)
136cc4ceb48SDaniel Vetter 		goto fail;
137cc4ceb48SDaniel Vetter 	state->planes = kcalloc(dev->mode_config.num_total_plane,
138cc4ceb48SDaniel Vetter 				sizeof(*state->planes), GFP_KERNEL);
139cc4ceb48SDaniel Vetter 	if (!state->planes)
140cc4ceb48SDaniel Vetter 		goto fail;
141cc4ceb48SDaniel Vetter 
1424e076c73SDaniel Vetter 	/*
1434e076c73SDaniel Vetter 	 * Because drm_atomic_state can be committed asynchronously we need our
1444e076c73SDaniel Vetter 	 * own reference and cannot rely on the on implied by drm_file in the
1454e076c73SDaniel Vetter 	 * ioctl call.
1464e076c73SDaniel Vetter 	 */
1474e076c73SDaniel Vetter 	drm_dev_get(dev);
148cc4ceb48SDaniel Vetter 	state->dev = dev;
149cc4ceb48SDaniel Vetter 
1506e22dc35SClaudio Suarez 	drm_dbg_atomic(dev, "Allocated atomic state %p\n", state);
151cc4ceb48SDaniel Vetter 
152036ef573SMaarten Lankhorst 	return 0;
153cc4ceb48SDaniel Vetter fail:
154036ef573SMaarten Lankhorst 	drm_atomic_state_default_release(state);
155036ef573SMaarten Lankhorst 	return -ENOMEM;
156036ef573SMaarten Lankhorst }
157036ef573SMaarten Lankhorst EXPORT_SYMBOL(drm_atomic_state_init);
158cc4ceb48SDaniel Vetter 
159036ef573SMaarten Lankhorst /**
160036ef573SMaarten Lankhorst  * drm_atomic_state_alloc - allocate atomic state
161036ef573SMaarten Lankhorst  * @dev: DRM device
162036ef573SMaarten Lankhorst  *
163036ef573SMaarten Lankhorst  * This allocates an empty atomic state to track updates.
164036ef573SMaarten Lankhorst  */
165036ef573SMaarten Lankhorst struct drm_atomic_state *
drm_atomic_state_alloc(struct drm_device * dev)166036ef573SMaarten Lankhorst drm_atomic_state_alloc(struct drm_device *dev)
167036ef573SMaarten Lankhorst {
168036ef573SMaarten Lankhorst 	struct drm_mode_config *config = &dev->mode_config;
169036ef573SMaarten Lankhorst 
170036ef573SMaarten Lankhorst 	if (!config->funcs->atomic_state_alloc) {
171ac7c7483SDawid Kurek 		struct drm_atomic_state *state;
172ac7c7483SDawid Kurek 
173036ef573SMaarten Lankhorst 		state = kzalloc(sizeof(*state), GFP_KERNEL);
174036ef573SMaarten Lankhorst 		if (!state)
175cc4ceb48SDaniel Vetter 			return NULL;
176036ef573SMaarten Lankhorst 		if (drm_atomic_state_init(dev, state) < 0) {
177036ef573SMaarten Lankhorst 			kfree(state);
178036ef573SMaarten Lankhorst 			return NULL;
179036ef573SMaarten Lankhorst 		}
180036ef573SMaarten Lankhorst 		return state;
181036ef573SMaarten Lankhorst 	}
182036ef573SMaarten Lankhorst 
183036ef573SMaarten Lankhorst 	return config->funcs->atomic_state_alloc(dev);
184cc4ceb48SDaniel Vetter }
185cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_state_alloc);
186cc4ceb48SDaniel Vetter 
187cc4ceb48SDaniel Vetter /**
188036ef573SMaarten Lankhorst  * drm_atomic_state_default_clear - clear base atomic state
189cc4ceb48SDaniel Vetter  * @state: atomic state
190cc4ceb48SDaniel Vetter  *
191036ef573SMaarten Lankhorst  * Default implementation for clearing atomic state.
192da6c0596SDaniel Vetter  * This should only be used by drivers which are still subclassing
193da6c0596SDaniel Vetter  * &drm_atomic_state and haven't switched to &drm_private_state yet.
194cc4ceb48SDaniel Vetter  */
drm_atomic_state_default_clear(struct drm_atomic_state * state)195036ef573SMaarten Lankhorst void drm_atomic_state_default_clear(struct drm_atomic_state *state)
196cc4ceb48SDaniel Vetter {
197cc4ceb48SDaniel Vetter 	struct drm_device *dev = state->dev;
1986f75cea6SDaniel Vetter 	struct drm_mode_config *config = &dev->mode_config;
199cc4ceb48SDaniel Vetter 	int i;
200cc4ceb48SDaniel Vetter 
2016e22dc35SClaudio Suarez 	drm_dbg_atomic(dev, "Clearing atomic state %p\n", state);
202cc4ceb48SDaniel Vetter 
203f52b69f1SDaniel Vetter 	for (i = 0; i < state->num_connector; i++) {
20463e83c1dSDaniel Vetter 		struct drm_connector *connector = state->connectors[i].ptr;
205cc4ceb48SDaniel Vetter 
206cc4ceb48SDaniel Vetter 		if (!connector)
207cc4ceb48SDaniel Vetter 			continue;
208cc4ceb48SDaniel Vetter 
209d2307deaSDave Airlie 		connector->funcs->atomic_destroy_state(connector,
21063e83c1dSDaniel Vetter 						       state->connectors[i].state);
21163e83c1dSDaniel Vetter 		state->connectors[i].ptr = NULL;
21263e83c1dSDaniel Vetter 		state->connectors[i].state = NULL;
213f0b408eeSVille Syrjälä 		state->connectors[i].old_state = NULL;
214f0b408eeSVille Syrjälä 		state->connectors[i].new_state = NULL;
215ad093607SThierry Reding 		drm_connector_put(connector);
216cc4ceb48SDaniel Vetter 	}
217cc4ceb48SDaniel Vetter 
2186f75cea6SDaniel Vetter 	for (i = 0; i < config->num_crtc; i++) {
2195d943aa6SDaniel Vetter 		struct drm_crtc *crtc = state->crtcs[i].ptr;
220cc4ceb48SDaniel Vetter 
221cc4ceb48SDaniel Vetter 		if (!crtc)
222cc4ceb48SDaniel Vetter 			continue;
223cc4ceb48SDaniel Vetter 
224cc4ceb48SDaniel Vetter 		crtc->funcs->atomic_destroy_state(crtc,
2255d943aa6SDaniel Vetter 						  state->crtcs[i].state);
2263b24f7d6SDaniel Vetter 
2275d943aa6SDaniel Vetter 		state->crtcs[i].ptr = NULL;
2285d943aa6SDaniel Vetter 		state->crtcs[i].state = NULL;
229f0b408eeSVille Syrjälä 		state->crtcs[i].old_state = NULL;
230f0b408eeSVille Syrjälä 		state->crtcs[i].new_state = NULL;
2314364bcb2SLeo Li 
2324364bcb2SLeo Li 		if (state->crtcs[i].commit) {
2334364bcb2SLeo Li 			drm_crtc_commit_put(state->crtcs[i].commit);
2344364bcb2SLeo Li 			state->crtcs[i].commit = NULL;
2354364bcb2SLeo Li 		}
236cc4ceb48SDaniel Vetter 	}
237cc4ceb48SDaniel Vetter 
2386f75cea6SDaniel Vetter 	for (i = 0; i < config->num_total_plane; i++) {
239b8b5342bSDaniel Vetter 		struct drm_plane *plane = state->planes[i].ptr;
240cc4ceb48SDaniel Vetter 
241cc4ceb48SDaniel Vetter 		if (!plane)
242cc4ceb48SDaniel Vetter 			continue;
243cc4ceb48SDaniel Vetter 
244cc4ceb48SDaniel Vetter 		plane->funcs->atomic_destroy_state(plane,
245b8b5342bSDaniel Vetter 						   state->planes[i].state);
246b8b5342bSDaniel Vetter 		state->planes[i].ptr = NULL;
247b8b5342bSDaniel Vetter 		state->planes[i].state = NULL;
248f0b408eeSVille Syrjälä 		state->planes[i].old_state = NULL;
249f0b408eeSVille Syrjälä 		state->planes[i].new_state = NULL;
250cc4ceb48SDaniel Vetter 	}
251b430c27aSPandiyan, Dhinakaran 
252b430c27aSPandiyan, Dhinakaran 	for (i = 0; i < state->num_private_objs; i++) {
253a4370c77SVille Syrjälä 		struct drm_private_obj *obj = state->private_objs[i].ptr;
254b430c27aSPandiyan, Dhinakaran 
255a4370c77SVille Syrjälä 		obj->funcs->atomic_destroy_state(obj,
256a4370c77SVille Syrjälä 						 state->private_objs[i].state);
257a4370c77SVille Syrjälä 		state->private_objs[i].ptr = NULL;
258a4370c77SVille Syrjälä 		state->private_objs[i].state = NULL;
259b5cb2e5aSVille Syrjälä 		state->private_objs[i].old_state = NULL;
260b5cb2e5aSVille Syrjälä 		state->private_objs[i].new_state = NULL;
261b430c27aSPandiyan, Dhinakaran 	}
262b430c27aSPandiyan, Dhinakaran 	state->num_private_objs = 0;
263b430c27aSPandiyan, Dhinakaran 
26421a01abbSMaarten Lankhorst 	if (state->fake_commit) {
26521a01abbSMaarten Lankhorst 		drm_crtc_commit_put(state->fake_commit);
26621a01abbSMaarten Lankhorst 		state->fake_commit = NULL;
26721a01abbSMaarten Lankhorst 	}
268cc4ceb48SDaniel Vetter }
269036ef573SMaarten Lankhorst EXPORT_SYMBOL(drm_atomic_state_default_clear);
270036ef573SMaarten Lankhorst 
271036ef573SMaarten Lankhorst /**
272036ef573SMaarten Lankhorst  * drm_atomic_state_clear - clear state object
273036ef573SMaarten Lankhorst  * @state: atomic state
274036ef573SMaarten Lankhorst  *
275036ef573SMaarten Lankhorst  * When the w/w mutex algorithm detects a deadlock we need to back off and drop
276036ef573SMaarten Lankhorst  * all locks. So someone else could sneak in and change the current modeset
277036ef573SMaarten Lankhorst  * configuration. Which means that all the state assembled in @state is no
278036ef573SMaarten Lankhorst  * longer an atomic update to the current state, but to some arbitrary earlier
279d574528aSDaniel Vetter  * state. Which could break assumptions the driver's
280d574528aSDaniel Vetter  * &drm_mode_config_funcs.atomic_check likely relies on.
281036ef573SMaarten Lankhorst  *
282036ef573SMaarten Lankhorst  * Hence we must clear all cached state and completely start over, using this
283036ef573SMaarten Lankhorst  * function.
284036ef573SMaarten Lankhorst  */
drm_atomic_state_clear(struct drm_atomic_state * state)285036ef573SMaarten Lankhorst void drm_atomic_state_clear(struct drm_atomic_state *state)
286036ef573SMaarten Lankhorst {
287036ef573SMaarten Lankhorst 	struct drm_device *dev = state->dev;
288036ef573SMaarten Lankhorst 	struct drm_mode_config *config = &dev->mode_config;
289036ef573SMaarten Lankhorst 
290036ef573SMaarten Lankhorst 	if (config->funcs->atomic_state_clear)
291036ef573SMaarten Lankhorst 		config->funcs->atomic_state_clear(state);
292036ef573SMaarten Lankhorst 	else
293036ef573SMaarten Lankhorst 		drm_atomic_state_default_clear(state);
294036ef573SMaarten Lankhorst }
295cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_state_clear);
296cc4ceb48SDaniel Vetter 
297cc4ceb48SDaniel Vetter /**
2980853695cSChris Wilson  * __drm_atomic_state_free - free all memory for an atomic state
2990853695cSChris Wilson  * @ref: This atomic state to deallocate
300cc4ceb48SDaniel Vetter  *
301cc4ceb48SDaniel Vetter  * This frees all memory associated with an atomic state, including all the
30242240c90SThierry Reding  * per-object state for planes, CRTCs and connectors.
303cc4ceb48SDaniel Vetter  */
__drm_atomic_state_free(struct kref * ref)3040853695cSChris Wilson void __drm_atomic_state_free(struct kref *ref)
305cc4ceb48SDaniel Vetter {
3060853695cSChris Wilson 	struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
3074e076c73SDaniel Vetter 	struct drm_device *dev = state->dev;
3084e076c73SDaniel Vetter 	struct drm_mode_config *config = &dev->mode_config;
309036ef573SMaarten Lankhorst 
310cc4ceb48SDaniel Vetter 	drm_atomic_state_clear(state);
311cc4ceb48SDaniel Vetter 
3126e22dc35SClaudio Suarez 	drm_dbg_atomic(state->dev, "Freeing atomic state %p\n", state);
313cc4ceb48SDaniel Vetter 
314036ef573SMaarten Lankhorst 	if (config->funcs->atomic_state_free) {
315036ef573SMaarten Lankhorst 		config->funcs->atomic_state_free(state);
316036ef573SMaarten Lankhorst 	} else {
317036ef573SMaarten Lankhorst 		drm_atomic_state_default_release(state);
318036ef573SMaarten Lankhorst 		kfree(state);
319036ef573SMaarten Lankhorst 	}
3204e076c73SDaniel Vetter 
3214e076c73SDaniel Vetter 	drm_dev_put(dev);
322cc4ceb48SDaniel Vetter }
3230853695cSChris Wilson EXPORT_SYMBOL(__drm_atomic_state_free);
324cc4ceb48SDaniel Vetter 
325cc4ceb48SDaniel Vetter /**
32642240c90SThierry Reding  * drm_atomic_get_crtc_state - get CRTC state
327cc4ceb48SDaniel Vetter  * @state: global atomic state object
32842240c90SThierry Reding  * @crtc: CRTC to get state object for
329cc4ceb48SDaniel Vetter  *
33042240c90SThierry Reding  * This function returns the CRTC state for the given CRTC, allocating it if
33142240c90SThierry Reding  * needed. It will also grab the relevant CRTC lock to make sure that the state
332cc4ceb48SDaniel Vetter  * is consistent.
333cc4ceb48SDaniel Vetter  *
334fb6473a4SDaniel Vetter  * WARNING: Drivers may only add new CRTC states to a @state if
335fb6473a4SDaniel Vetter  * drm_atomic_state.allow_modeset is set, or if it's a driver-internal commit
336fb6473a4SDaniel Vetter  * not created by userspace through an IOCTL call.
337fb6473a4SDaniel Vetter  *
338cc4ceb48SDaniel Vetter  * Returns:
339cc4ceb48SDaniel Vetter  * Either the allocated state or the error code encoded into the pointer. When
340cc4ceb48SDaniel Vetter  * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
341cc4ceb48SDaniel Vetter  * entire atomic sequence must be restarted. All other errors are fatal.
342cc4ceb48SDaniel Vetter  */
343cc4ceb48SDaniel Vetter struct drm_crtc_state *
drm_atomic_get_crtc_state(struct drm_atomic_state * state,struct drm_crtc * crtc)344cc4ceb48SDaniel Vetter drm_atomic_get_crtc_state(struct drm_atomic_state *state,
345cc4ceb48SDaniel Vetter 			  struct drm_crtc *crtc)
346cc4ceb48SDaniel Vetter {
3471b26a5e1SMaarten Lankhorst 	int ret, index = drm_crtc_index(crtc);
348cc4ceb48SDaniel Vetter 	struct drm_crtc_state *crtc_state;
349cc4ceb48SDaniel Vetter 
3507f4eaa89SMaarten Lankhorst 	WARN_ON(!state->acquire_ctx);
3517f4eaa89SMaarten Lankhorst 
3521b26a5e1SMaarten Lankhorst 	crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
3531b26a5e1SMaarten Lankhorst 	if (crtc_state)
3541b26a5e1SMaarten Lankhorst 		return crtc_state;
355cc4ceb48SDaniel Vetter 
356cc4ceb48SDaniel Vetter 	ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx);
357cc4ceb48SDaniel Vetter 	if (ret)
358cc4ceb48SDaniel Vetter 		return ERR_PTR(ret);
359cc4ceb48SDaniel Vetter 
360cc4ceb48SDaniel Vetter 	crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
361cc4ceb48SDaniel Vetter 	if (!crtc_state)
362cc4ceb48SDaniel Vetter 		return ERR_PTR(-ENOMEM);
363cc4ceb48SDaniel Vetter 
3645d943aa6SDaniel Vetter 	state->crtcs[index].state = crtc_state;
365581e49feSMaarten Lankhorst 	state->crtcs[index].old_state = crtc->state;
366581e49feSMaarten Lankhorst 	state->crtcs[index].new_state = crtc_state;
3675d943aa6SDaniel Vetter 	state->crtcs[index].ptr = crtc;
368cc4ceb48SDaniel Vetter 	crtc_state->state = state;
369cc4ceb48SDaniel Vetter 
3706e22dc35SClaudio Suarez 	drm_dbg_atomic(state->dev, "Added [CRTC:%d:%s] %p state to %p\n",
371fa3ab4c2SVille Syrjälä 		       crtc->base.id, crtc->name, crtc_state, state);
372cc4ceb48SDaniel Vetter 
373cc4ceb48SDaniel Vetter 	return crtc_state;
374cc4ceb48SDaniel Vetter }
375cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_get_crtc_state);
376cc4ceb48SDaniel Vetter 
drm_atomic_crtc_check(const struct drm_crtc_state * old_crtc_state,const struct drm_crtc_state * new_crtc_state)377b2432adfSVille Syrjälä static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state,
378b2432adfSVille Syrjälä 				 const struct drm_crtc_state *new_crtc_state)
3795e743737SRob Clark {
380b2432adfSVille Syrjälä 	struct drm_crtc *crtc = new_crtc_state->crtc;
381b2432adfSVille Syrjälä 
3825e743737SRob Clark 	/* NOTE: we explicitly don't enforce constraints such as primary
3835e743737SRob Clark 	 * layer covering entire screen, since that is something we want
3845e743737SRob Clark 	 * to allow (on hw that supports it).  For hw that does not, it
3855e743737SRob Clark 	 * should be checked in driver's crtc->atomic_check() vfunc.
3865e743737SRob Clark 	 *
3875e743737SRob Clark 	 * TODO: Add generic modeset state checks once we support those.
3885e743737SRob Clark 	 */
389eab3bbefSDaniel Vetter 
390b2432adfSVille Syrjälä 	if (new_crtc_state->active && !new_crtc_state->enable) {
3916e22dc35SClaudio Suarez 		drm_dbg_atomic(crtc->dev,
3926e22dc35SClaudio Suarez 			       "[CRTC:%d:%s] active without enabled\n",
393fa3ab4c2SVille Syrjälä 			       crtc->base.id, crtc->name);
394eab3bbefSDaniel Vetter 		return -EINVAL;
395eab3bbefSDaniel Vetter 	}
396eab3bbefSDaniel Vetter 
39799cf4a29SDaniel Stone 	/* The state->enable vs. state->mode_blob checks can be WARN_ON,
39899cf4a29SDaniel Stone 	 * as this is a kernel-internal detail that userspace should never
399060726c5SBeatriz Martins de Carvalho 	 * be able to trigger.
400060726c5SBeatriz Martins de Carvalho 	 */
40199cf4a29SDaniel Stone 	if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
402b2432adfSVille Syrjälä 	    WARN_ON(new_crtc_state->enable && !new_crtc_state->mode_blob)) {
4036e22dc35SClaudio Suarez 		drm_dbg_atomic(crtc->dev,
4046e22dc35SClaudio Suarez 			       "[CRTC:%d:%s] enabled without mode blob\n",
405fa3ab4c2SVille Syrjälä 			       crtc->base.id, crtc->name);
40699cf4a29SDaniel Stone 		return -EINVAL;
40799cf4a29SDaniel Stone 	}
40899cf4a29SDaniel Stone 
40999cf4a29SDaniel Stone 	if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
410b2432adfSVille Syrjälä 	    WARN_ON(!new_crtc_state->enable && new_crtc_state->mode_blob)) {
4116e22dc35SClaudio Suarez 		drm_dbg_atomic(crtc->dev,
4126e22dc35SClaudio Suarez 			       "[CRTC:%d:%s] disabled with mode blob\n",
413fa3ab4c2SVille Syrjälä 			       crtc->base.id, crtc->name);
41499cf4a29SDaniel Stone 		return -EINVAL;
41599cf4a29SDaniel Stone 	}
41699cf4a29SDaniel Stone 
4174cba6850SDaniel Vetter 	/*
4184cba6850SDaniel Vetter 	 * Reject event generation for when a CRTC is off and stays off.
4194cba6850SDaniel Vetter 	 * It wouldn't be hard to implement this, but userspace has a track
4204cba6850SDaniel Vetter 	 * record of happily burning through 100% cpu (or worse, crash) when the
4214cba6850SDaniel Vetter 	 * display pipe is suspended. To avoid all that fun just reject updates
4224cba6850SDaniel Vetter 	 * that ask for events since likely that indicates a bug in the
4234cba6850SDaniel Vetter 	 * compositor's drawing loop. This is consistent with the vblank IOCTL
4244cba6850SDaniel Vetter 	 * and legacy page_flip IOCTL which also reject service on a disabled
4254cba6850SDaniel Vetter 	 * pipe.
4264cba6850SDaniel Vetter 	 */
427b2432adfSVille Syrjälä 	if (new_crtc_state->event &&
428b2432adfSVille Syrjälä 	    !new_crtc_state->active && !old_crtc_state->active) {
4296e22dc35SClaudio Suarez 		drm_dbg_atomic(crtc->dev,
4306e22dc35SClaudio Suarez 			       "[CRTC:%d:%s] requesting event but off\n",
4316ac7c548SRussell King 			       crtc->base.id, crtc->name);
4324cba6850SDaniel Vetter 		return -EINVAL;
4334cba6850SDaniel Vetter 	}
4344cba6850SDaniel Vetter 
4355e743737SRob Clark 	return 0;
4365e743737SRob Clark }
4375e743737SRob Clark 
drm_atomic_crtc_print_state(struct drm_printer * p,const struct drm_crtc_state * state)438fceffb32SRob Clark static void drm_atomic_crtc_print_state(struct drm_printer *p,
439fceffb32SRob Clark 		const struct drm_crtc_state *state)
440fceffb32SRob Clark {
441fceffb32SRob Clark 	struct drm_crtc *crtc = state->crtc;
442fceffb32SRob Clark 
443fceffb32SRob Clark 	drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name);
444fceffb32SRob Clark 	drm_printf(p, "\tenable=%d\n", state->enable);
445fceffb32SRob Clark 	drm_printf(p, "\tactive=%d\n", state->active);
4461452c25bSSean Paul 	drm_printf(p, "\tself_refresh_active=%d\n", state->self_refresh_active);
447fceffb32SRob Clark 	drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed);
448fceffb32SRob Clark 	drm_printf(p, "\tmode_changed=%d\n", state->mode_changed);
449fceffb32SRob Clark 	drm_printf(p, "\tactive_changed=%d\n", state->active_changed);
450fceffb32SRob Clark 	drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed);
451fceffb32SRob Clark 	drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
452fceffb32SRob Clark 	drm_printf(p, "\tplane_mask=%x\n", state->plane_mask);
453fceffb32SRob Clark 	drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
454fceffb32SRob Clark 	drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
455fceffb32SRob Clark 	drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
456fceffb32SRob Clark 
457fceffb32SRob Clark 	if (crtc->funcs->atomic_print_state)
458fceffb32SRob Clark 		crtc->funcs->atomic_print_state(p, state);
459fceffb32SRob Clark }
460fceffb32SRob Clark 
drm_atomic_connector_check(struct drm_connector * connector,struct drm_connector_state * state)461935774cdSBrian Starkey static int drm_atomic_connector_check(struct drm_connector *connector,
462935774cdSBrian Starkey 		struct drm_connector_state *state)
463935774cdSBrian Starkey {
464935774cdSBrian Starkey 	struct drm_crtc_state *crtc_state;
465935774cdSBrian Starkey 	struct drm_writeback_job *writeback_job = state->writeback_job;
46647e22ff1SRadhakrishna Sripada 	const struct drm_display_info *info = &connector->display_info;
46747e22ff1SRadhakrishna Sripada 
46847e22ff1SRadhakrishna Sripada 	state->max_bpc = info->bpc ? info->bpc : 8;
46947e22ff1SRadhakrishna Sripada 	if (connector->max_bpc_property)
47047e22ff1SRadhakrishna Sripada 		state->max_bpc = min(state->max_bpc, state->max_requested_bpc);
471935774cdSBrian Starkey 
472935774cdSBrian Starkey 	if ((connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) || !writeback_job)
473935774cdSBrian Starkey 		return 0;
474935774cdSBrian Starkey 
475935774cdSBrian Starkey 	if (writeback_job->fb && !state->crtc) {
4766e22dc35SClaudio Suarez 		drm_dbg_atomic(connector->dev,
4776e22dc35SClaudio Suarez 			       "[CONNECTOR:%d:%s] framebuffer without CRTC\n",
478935774cdSBrian Starkey 			       connector->base.id, connector->name);
479935774cdSBrian Starkey 		return -EINVAL;
480935774cdSBrian Starkey 	}
481935774cdSBrian Starkey 
482935774cdSBrian Starkey 	if (state->crtc)
483935774cdSBrian Starkey 		crtc_state = drm_atomic_get_existing_crtc_state(state->state,
484935774cdSBrian Starkey 								state->crtc);
485935774cdSBrian Starkey 
486935774cdSBrian Starkey 	if (writeback_job->fb && !crtc_state->active) {
4876e22dc35SClaudio Suarez 		drm_dbg_atomic(connector->dev,
4886e22dc35SClaudio Suarez 			       "[CONNECTOR:%d:%s] has framebuffer, but [CRTC:%d] is off\n",
489935774cdSBrian Starkey 			       connector->base.id, connector->name,
490935774cdSBrian Starkey 			       state->crtc->base.id);
491935774cdSBrian Starkey 		return -EINVAL;
492935774cdSBrian Starkey 	}
493935774cdSBrian Starkey 
4948581d510SLowry Li (Arm Technology China) 	if (!writeback_job->fb) {
4958581d510SLowry Li (Arm Technology China) 		if (writeback_job->out_fence) {
4966e22dc35SClaudio Suarez 			drm_dbg_atomic(connector->dev,
4976e22dc35SClaudio Suarez 				       "[CONNECTOR:%d:%s] requesting out-fence without framebuffer\n",
498b13cc8ddSBrian Starkey 				       connector->base.id, connector->name);
499b13cc8ddSBrian Starkey 			return -EINVAL;
500b13cc8ddSBrian Starkey 		}
501b13cc8ddSBrian Starkey 
5028581d510SLowry Li (Arm Technology China) 		drm_writeback_cleanup_job(writeback_job);
5038581d510SLowry Li (Arm Technology China) 		state->writeback_job = NULL;
5048581d510SLowry Li (Arm Technology China) 	}
5058581d510SLowry Li (Arm Technology China) 
506935774cdSBrian Starkey 	return 0;
507935774cdSBrian Starkey }
508935774cdSBrian Starkey 
509935774cdSBrian Starkey /**
510cc4ceb48SDaniel Vetter  * drm_atomic_get_plane_state - get plane state
511cc4ceb48SDaniel Vetter  * @state: global atomic state object
512cc4ceb48SDaniel Vetter  * @plane: plane to get state object for
513cc4ceb48SDaniel Vetter  *
514cc4ceb48SDaniel Vetter  * This function returns the plane state for the given plane, allocating it if
515cc4ceb48SDaniel Vetter  * needed. It will also grab the relevant plane lock to make sure that the state
516cc4ceb48SDaniel Vetter  * is consistent.
517cc4ceb48SDaniel Vetter  *
518cc4ceb48SDaniel Vetter  * Returns:
519cc4ceb48SDaniel Vetter  * Either the allocated state or the error code encoded into the pointer. When
520cc4ceb48SDaniel Vetter  * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
521cc4ceb48SDaniel Vetter  * entire atomic sequence must be restarted. All other errors are fatal.
522cc4ceb48SDaniel Vetter  */
523cc4ceb48SDaniel Vetter struct drm_plane_state *
drm_atomic_get_plane_state(struct drm_atomic_state * state,struct drm_plane * plane)524cc4ceb48SDaniel Vetter drm_atomic_get_plane_state(struct drm_atomic_state *state,
525cc4ceb48SDaniel Vetter 			  struct drm_plane *plane)
526cc4ceb48SDaniel Vetter {
5271b26a5e1SMaarten Lankhorst 	int ret, index = drm_plane_index(plane);
528cc4ceb48SDaniel Vetter 	struct drm_plane_state *plane_state;
529cc4ceb48SDaniel Vetter 
5307f4eaa89SMaarten Lankhorst 	WARN_ON(!state->acquire_ctx);
5317f4eaa89SMaarten Lankhorst 
532e00fb856SVille Syrjälä 	/* the legacy pointers should never be set */
533e00fb856SVille Syrjälä 	WARN_ON(plane->fb);
534e00fb856SVille Syrjälä 	WARN_ON(plane->old_fb);
535e00fb856SVille Syrjälä 	WARN_ON(plane->crtc);
536e00fb856SVille Syrjälä 
5371b26a5e1SMaarten Lankhorst 	plane_state = drm_atomic_get_existing_plane_state(state, plane);
5381b26a5e1SMaarten Lankhorst 	if (plane_state)
5391b26a5e1SMaarten Lankhorst 		return plane_state;
540cc4ceb48SDaniel Vetter 
5414d02e2deSDaniel Vetter 	ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
542cc4ceb48SDaniel Vetter 	if (ret)
543cc4ceb48SDaniel Vetter 		return ERR_PTR(ret);
544cc4ceb48SDaniel Vetter 
545cc4ceb48SDaniel Vetter 	plane_state = plane->funcs->atomic_duplicate_state(plane);
546cc4ceb48SDaniel Vetter 	if (!plane_state)
547cc4ceb48SDaniel Vetter 		return ERR_PTR(-ENOMEM);
548cc4ceb48SDaniel Vetter 
549b8b5342bSDaniel Vetter 	state->planes[index].state = plane_state;
550b8b5342bSDaniel Vetter 	state->planes[index].ptr = plane;
551581e49feSMaarten Lankhorst 	state->planes[index].old_state = plane->state;
552581e49feSMaarten Lankhorst 	state->planes[index].new_state = plane_state;
553cc4ceb48SDaniel Vetter 	plane_state->state = state;
554cc4ceb48SDaniel Vetter 
5556e22dc35SClaudio Suarez 	drm_dbg_atomic(plane->dev, "Added [PLANE:%d:%s] %p state to %p\n",
5569f4c97a2SVille Syrjälä 		       plane->base.id, plane->name, plane_state, state);
557cc4ceb48SDaniel Vetter 
558cc4ceb48SDaniel Vetter 	if (plane_state->crtc) {
559cc4ceb48SDaniel Vetter 		struct drm_crtc_state *crtc_state;
560cc4ceb48SDaniel Vetter 
561cc4ceb48SDaniel Vetter 		crtc_state = drm_atomic_get_crtc_state(state,
562cc4ceb48SDaniel Vetter 						       plane_state->crtc);
563cc4ceb48SDaniel Vetter 		if (IS_ERR(crtc_state))
564cc4ceb48SDaniel Vetter 			return ERR_CAST(crtc_state);
565cc4ceb48SDaniel Vetter 	}
566cc4ceb48SDaniel Vetter 
567cc4ceb48SDaniel Vetter 	return plane_state;
568cc4ceb48SDaniel Vetter }
569cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_get_plane_state);
570cc4ceb48SDaniel Vetter 
571f8aeb41cSDaniel Vetter static bool
plane_switching_crtc(const struct drm_plane_state * old_plane_state,const struct drm_plane_state * new_plane_state)572d9be05b7SVille Syrjälä plane_switching_crtc(const struct drm_plane_state *old_plane_state,
573d9be05b7SVille Syrjälä 		     const struct drm_plane_state *new_plane_state)
574f8aeb41cSDaniel Vetter {
575d9be05b7SVille Syrjälä 	if (!old_plane_state->crtc || !new_plane_state->crtc)
576f8aeb41cSDaniel Vetter 		return false;
577f8aeb41cSDaniel Vetter 
578d9be05b7SVille Syrjälä 	if (old_plane_state->crtc == new_plane_state->crtc)
579f8aeb41cSDaniel Vetter 		return false;
580f8aeb41cSDaniel Vetter 
581f8aeb41cSDaniel Vetter 	/* This could be refined, but currently there's no helper or driver code
582f8aeb41cSDaniel Vetter 	 * to implement direct switching of active planes nor userspace to take
583f8aeb41cSDaniel Vetter 	 * advantage of more direct plane switching without the intermediate
584f8aeb41cSDaniel Vetter 	 * full OFF state.
585f8aeb41cSDaniel Vetter 	 */
586f8aeb41cSDaniel Vetter 	return true;
587f8aeb41cSDaniel Vetter }
588f8aeb41cSDaniel Vetter 
589ac9c9256SRob Clark /**
5905e743737SRob Clark  * drm_atomic_plane_check - check plane state
591d9be05b7SVille Syrjälä  * @old_plane_state: old plane state to check
592d9be05b7SVille Syrjälä  * @new_plane_state: new plane state to check
5935e743737SRob Clark  *
5945e743737SRob Clark  * Provides core sanity checks for plane state.
5955e743737SRob Clark  *
5965e743737SRob Clark  * RETURNS:
5975e743737SRob Clark  * Zero on success, error code on failure
5985e743737SRob Clark  */
drm_atomic_plane_check(const struct drm_plane_state * old_plane_state,const struct drm_plane_state * new_plane_state)599d9be05b7SVille Syrjälä static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
600d9be05b7SVille Syrjälä 				  const struct drm_plane_state *new_plane_state)
6015e743737SRob Clark {
602d9be05b7SVille Syrjälä 	struct drm_plane *plane = new_plane_state->plane;
603d9be05b7SVille Syrjälä 	struct drm_crtc *crtc = new_plane_state->crtc;
6041c0a80f1SDmitry Baryshkov 	const struct drm_framebuffer *fb = new_plane_state->fb;
605b881ba8fSDmitry Baryshkov 	unsigned int fb_width, fb_height;
606b881ba8fSDmitry Baryshkov 	struct drm_mode_rect *clips;
607b881ba8fSDmitry Baryshkov 	uint32_t num_clips;
6085e743737SRob Clark 
6091c0a80f1SDmitry Baryshkov 	/* either *both* CRTC and FB must be set, or neither */
6101c0a80f1SDmitry Baryshkov 	if (crtc && !fb) {
6111c0a80f1SDmitry Baryshkov 		drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] CRTC set but no FB\n",
612b6f690abSVille Syrjälä 			       plane->base.id, plane->name);
6135e743737SRob Clark 		return -EINVAL;
6141c0a80f1SDmitry Baryshkov 	} else if (fb && !crtc) {
6151c0a80f1SDmitry Baryshkov 		drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] FB set but no CRTC\n",
6161c0a80f1SDmitry Baryshkov 			       plane->base.id, plane->name);
6175e743737SRob Clark 		return -EINVAL;
6185e743737SRob Clark 	}
6195e743737SRob Clark 
6205e743737SRob Clark 	/* if disabled, we don't care about the rest of the state: */
621d9be05b7SVille Syrjälä 	if (!crtc)
6225e743737SRob Clark 		return 0;
6235e743737SRob Clark 
6245e743737SRob Clark 	/* Check whether this plane is usable on this CRTC */
625d9be05b7SVille Syrjälä 	if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
6266e22dc35SClaudio Suarez 		drm_dbg_atomic(plane->dev,
6276e22dc35SClaudio Suarez 			       "Invalid [CRTC:%d:%s] for [PLANE:%d:%s]\n",
628d9be05b7SVille Syrjälä 			       crtc->base.id, crtc->name,
629b6f690abSVille Syrjälä 			       plane->base.id, plane->name);
6305e743737SRob Clark 		return -EINVAL;
6315e743737SRob Clark 	}
6325e743737SRob Clark 
633b881ba8fSDmitry Baryshkov 	/* Check whether this plane supports the fb pixel format. */
634*1d36db2bSVille Syrjälä 	if (!drm_plane_has_format(plane, fb->format->format, fb->modifier)) {
635b881ba8fSDmitry Baryshkov 		drm_dbg_atomic(plane->dev,
636b881ba8fSDmitry Baryshkov 			       "[PLANE:%d:%s] invalid pixel format %p4cc, modifier 0x%llx\n",
637b881ba8fSDmitry Baryshkov 			       plane->base.id, plane->name,
638b881ba8fSDmitry Baryshkov 			       &fb->format->format, fb->modifier);
639*1d36db2bSVille Syrjälä 		return -EINVAL;
640b881ba8fSDmitry Baryshkov 	}
641b881ba8fSDmitry Baryshkov 
6425e743737SRob Clark 	/* Give drivers some help against integer overflows */
643d9be05b7SVille Syrjälä 	if (new_plane_state->crtc_w > INT_MAX ||
644d9be05b7SVille Syrjälä 	    new_plane_state->crtc_x > INT_MAX - (int32_t) new_plane_state->crtc_w ||
645d9be05b7SVille Syrjälä 	    new_plane_state->crtc_h > INT_MAX ||
646d9be05b7SVille Syrjälä 	    new_plane_state->crtc_y > INT_MAX - (int32_t) new_plane_state->crtc_h) {
6476e22dc35SClaudio Suarez 		drm_dbg_atomic(plane->dev,
6486e22dc35SClaudio Suarez 			       "[PLANE:%d:%s] invalid CRTC coordinates %ux%u+%d+%d\n",
649b6f690abSVille Syrjälä 			       plane->base.id, plane->name,
650d9be05b7SVille Syrjälä 			       new_plane_state->crtc_w, new_plane_state->crtc_h,
651d9be05b7SVille Syrjälä 			       new_plane_state->crtc_x, new_plane_state->crtc_y);
6525e743737SRob Clark 		return -ERANGE;
6535e743737SRob Clark 	}
6545e743737SRob Clark 
655b881ba8fSDmitry Baryshkov 	fb_width = fb->width << 16;
656b881ba8fSDmitry Baryshkov 	fb_height = fb->height << 16;
6575e743737SRob Clark 
658b881ba8fSDmitry Baryshkov 	/* Make sure source coordinates are inside the fb. */
659b881ba8fSDmitry Baryshkov 	if (new_plane_state->src_w > fb_width ||
660b881ba8fSDmitry Baryshkov 	    new_plane_state->src_x > fb_width - new_plane_state->src_w ||
661b881ba8fSDmitry Baryshkov 	    new_plane_state->src_h > fb_height ||
662b881ba8fSDmitry Baryshkov 	    new_plane_state->src_y > fb_height - new_plane_state->src_h) {
663b881ba8fSDmitry Baryshkov 		drm_dbg_atomic(plane->dev,
664b881ba8fSDmitry Baryshkov 			       "[PLANE:%d:%s] invalid source coordinates "
665b881ba8fSDmitry Baryshkov 			       "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
666b881ba8fSDmitry Baryshkov 			       plane->base.id, plane->name,
667b881ba8fSDmitry Baryshkov 			       new_plane_state->src_w >> 16,
668b881ba8fSDmitry Baryshkov 			       ((new_plane_state->src_w & 0xffff) * 15625) >> 10,
669b881ba8fSDmitry Baryshkov 			       new_plane_state->src_h >> 16,
670b881ba8fSDmitry Baryshkov 			       ((new_plane_state->src_h & 0xffff) * 15625) >> 10,
671b881ba8fSDmitry Baryshkov 			       new_plane_state->src_x >> 16,
672b881ba8fSDmitry Baryshkov 			       ((new_plane_state->src_x & 0xffff) * 15625) >> 10,
673b881ba8fSDmitry Baryshkov 			       new_plane_state->src_y >> 16,
674b881ba8fSDmitry Baryshkov 			       ((new_plane_state->src_y & 0xffff) * 15625) >> 10,
675b881ba8fSDmitry Baryshkov 			       fb->width, fb->height);
676b881ba8fSDmitry Baryshkov 		return -ENOSPC;
677b881ba8fSDmitry Baryshkov 	}
678b881ba8fSDmitry Baryshkov 
679b881ba8fSDmitry Baryshkov 	clips = __drm_plane_get_damage_clips(new_plane_state);
680b881ba8fSDmitry Baryshkov 	num_clips = drm_plane_get_damage_clips_count(new_plane_state);
681b881ba8fSDmitry Baryshkov 
682b881ba8fSDmitry Baryshkov 	/* Make sure damage clips are valid and inside the fb. */
683b881ba8fSDmitry Baryshkov 	while (num_clips > 0) {
684b881ba8fSDmitry Baryshkov 		if (clips->x1 >= clips->x2 ||
685b881ba8fSDmitry Baryshkov 		    clips->y1 >= clips->y2 ||
686b881ba8fSDmitry Baryshkov 		    clips->x1 < 0 ||
687b881ba8fSDmitry Baryshkov 		    clips->y1 < 0 ||
688b881ba8fSDmitry Baryshkov 		    clips->x2 > fb_width ||
689b881ba8fSDmitry Baryshkov 		    clips->y2 > fb_height) {
690b881ba8fSDmitry Baryshkov 			drm_dbg_atomic(plane->dev,
691b881ba8fSDmitry Baryshkov 				       "[PLANE:%d:%s] invalid damage clip %d %d %d %d\n",
692b881ba8fSDmitry Baryshkov 				       plane->base.id, plane->name, clips->x1,
693b881ba8fSDmitry Baryshkov 				       clips->y1, clips->x2, clips->y2);
694b881ba8fSDmitry Baryshkov 			return -EINVAL;
695b881ba8fSDmitry Baryshkov 		}
696b881ba8fSDmitry Baryshkov 		clips++;
697b881ba8fSDmitry Baryshkov 		num_clips--;
698b881ba8fSDmitry Baryshkov 	}
699d3b21767SLukasz Spintzyk 
700d9be05b7SVille Syrjälä 	if (plane_switching_crtc(old_plane_state, new_plane_state)) {
7016e22dc35SClaudio Suarez 		drm_dbg_atomic(plane->dev,
7026e22dc35SClaudio Suarez 			       "[PLANE:%d:%s] switching CRTC directly\n",
7039f4c97a2SVille Syrjälä 			       plane->base.id, plane->name);
704f8aeb41cSDaniel Vetter 		return -EINVAL;
705f8aeb41cSDaniel Vetter 	}
706f8aeb41cSDaniel Vetter 
7075e743737SRob Clark 	return 0;
7085e743737SRob Clark }
7095e743737SRob Clark 
drm_atomic_plane_print_state(struct drm_printer * p,const struct drm_plane_state * state)710fceffb32SRob Clark static void drm_atomic_plane_print_state(struct drm_printer *p,
711fceffb32SRob Clark 		const struct drm_plane_state *state)
712fceffb32SRob Clark {
713fceffb32SRob Clark 	struct drm_plane *plane = state->plane;
714fceffb32SRob Clark 	struct drm_rect src  = drm_plane_state_src(state);
715fceffb32SRob Clark 	struct drm_rect dest = drm_plane_state_dest(state);
716fceffb32SRob Clark 
717fceffb32SRob Clark 	drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name);
718fceffb32SRob Clark 	drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
719fceffb32SRob Clark 	drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0);
720f02b604bSNoralf Trønnes 	if (state->fb)
721f02b604bSNoralf Trønnes 		drm_framebuffer_print_info(p, 2, state->fb);
722fceffb32SRob Clark 	drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
723fceffb32SRob Clark 	drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
724fceffb32SRob Clark 	drm_printf(p, "\trotation=%x\n", state->rotation);
725f8878bb2SBenjamin Gaignard 	drm_printf(p, "\tnormalized-zpos=%x\n", state->normalized_zpos);
72656dbbaffSVille Syrjälä 	drm_printf(p, "\tcolor-encoding=%s\n",
72756dbbaffSVille Syrjälä 		   drm_get_color_encoding_name(state->color_encoding));
72856dbbaffSVille Syrjälä 	drm_printf(p, "\tcolor-range=%s\n",
72956dbbaffSVille Syrjälä 		   drm_get_color_range_name(state->color_range));
73024013b93SMelissa Wen 	drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
731fceffb32SRob Clark 
732fceffb32SRob Clark 	if (plane->funcs->atomic_print_state)
733fceffb32SRob Clark 		plane->funcs->atomic_print_state(p, state);
734fceffb32SRob Clark }
735fceffb32SRob Clark 
7365e743737SRob Clark /**
737da6c0596SDaniel Vetter  * DOC: handling driver private state
738da6c0596SDaniel Vetter  *
739da6c0596SDaniel Vetter  * Very often the DRM objects exposed to userspace in the atomic modeset api
740da6c0596SDaniel Vetter  * (&drm_connector, &drm_crtc and &drm_plane) do not map neatly to the
741da6c0596SDaniel Vetter  * underlying hardware. Especially for any kind of shared resources (e.g. shared
742da6c0596SDaniel Vetter  * clocks, scaler units, bandwidth and fifo limits shared among a group of
743da6c0596SDaniel Vetter  * planes or CRTCs, and so on) it makes sense to model these as independent
744da6c0596SDaniel Vetter  * objects. Drivers then need to do similar state tracking and commit ordering for
7450ae865efSCai Huoqing  * such private (since not exposed to userspace) objects as the atomic core and
746da6c0596SDaniel Vetter  * helpers already provide for connectors, planes and CRTCs.
747da6c0596SDaniel Vetter  *
748da6c0596SDaniel Vetter  * To make this easier on drivers the atomic core provides some support to track
749da6c0596SDaniel Vetter  * driver private state objects using struct &drm_private_obj, with the
750da6c0596SDaniel Vetter  * associated state struct &drm_private_state.
751da6c0596SDaniel Vetter  *
752da6c0596SDaniel Vetter  * Similar to userspace-exposed objects, private state structures can be
7530380c684SDaniel Vetter  * acquired by calling drm_atomic_get_private_obj_state(). This also takes care
7540380c684SDaniel Vetter  * of locking, hence drivers should not have a need to call drm_modeset_lock()
7550380c684SDaniel Vetter  * directly. Sequence of the actual hardware state commit is not handled,
7560380c684SDaniel Vetter  * drivers might need to keep track of struct drm_crtc_commit within subclassed
7570380c684SDaniel Vetter  * structure of &drm_private_state as necessary, e.g. similar to
7580380c684SDaniel Vetter  * &drm_plane_state.commit. See also &drm_atomic_state.fake_commit.
759da6c0596SDaniel Vetter  *
760da6c0596SDaniel Vetter  * All private state structures contained in a &drm_atomic_state update can be
761da6c0596SDaniel Vetter  * iterated using for_each_oldnew_private_obj_in_state(),
762da6c0596SDaniel Vetter  * for_each_new_private_obj_in_state() and for_each_old_private_obj_in_state().
763da6c0596SDaniel Vetter  * Drivers are recommended to wrap these for each type of driver private state
764da6c0596SDaniel Vetter  * object they have, filtering on &drm_private_obj.funcs using for_each_if(), at
765da6c0596SDaniel Vetter  * least if they want to iterate over all objects of a given type.
766da6c0596SDaniel Vetter  *
767da6c0596SDaniel Vetter  * An earlier way to handle driver private state was by subclassing struct
768da6c0596SDaniel Vetter  * &drm_atomic_state. But since that encourages non-standard ways to implement
769da6c0596SDaniel Vetter  * the check/commit split atomic requires (by using e.g. "check and rollback or
770da6c0596SDaniel Vetter  * commit instead" of "duplicate state, check, then either commit or release
771da6c0596SDaniel Vetter  * duplicated state) it is deprecated in favour of using &drm_private_state.
772da6c0596SDaniel Vetter  */
773da6c0596SDaniel Vetter 
774da6c0596SDaniel Vetter /**
775a4370c77SVille Syrjälä  * drm_atomic_private_obj_init - initialize private object
776b962a120SRob Clark  * @dev: DRM device this object will be attached to
777a4370c77SVille Syrjälä  * @obj: private object
778a4370c77SVille Syrjälä  * @state: initial private object state
779a4370c77SVille Syrjälä  * @funcs: pointer to the struct of function pointers that identify the object
780a4370c77SVille Syrjälä  * type
781a4370c77SVille Syrjälä  *
782a4370c77SVille Syrjälä  * Initialize the private object, which can be embedded into any
783a4370c77SVille Syrjälä  * driver private object that needs its own atomic state.
784a4370c77SVille Syrjälä  */
785a4370c77SVille Syrjälä 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)786b962a120SRob Clark drm_atomic_private_obj_init(struct drm_device *dev,
787b962a120SRob Clark 			    struct drm_private_obj *obj,
788a4370c77SVille Syrjälä 			    struct drm_private_state *state,
789a4370c77SVille Syrjälä 			    const struct drm_private_state_funcs *funcs)
790a4370c77SVille Syrjälä {
791a4370c77SVille Syrjälä 	memset(obj, 0, sizeof(*obj));
792a4370c77SVille Syrjälä 
793b962a120SRob Clark 	drm_modeset_lock_init(&obj->lock);
794b962a120SRob Clark 
795a4370c77SVille Syrjälä 	obj->state = state;
796a4370c77SVille Syrjälä 	obj->funcs = funcs;
797b962a120SRob Clark 	list_add_tail(&obj->head, &dev->mode_config.privobj_list);
79897a1f01bSMaxime Ripard 
79997a1f01bSMaxime Ripard 	state->obj = obj;
800a4370c77SVille Syrjälä }
801a4370c77SVille Syrjälä EXPORT_SYMBOL(drm_atomic_private_obj_init);
802a4370c77SVille Syrjälä 
803a4370c77SVille Syrjälä /**
804a4370c77SVille Syrjälä  * drm_atomic_private_obj_fini - finalize private object
805a4370c77SVille Syrjälä  * @obj: private object
806a4370c77SVille Syrjälä  *
807a4370c77SVille Syrjälä  * Finalize the private object.
808a4370c77SVille Syrjälä  */
809a4370c77SVille Syrjälä void
drm_atomic_private_obj_fini(struct drm_private_obj * obj)810a4370c77SVille Syrjälä drm_atomic_private_obj_fini(struct drm_private_obj *obj)
811a4370c77SVille Syrjälä {
812b962a120SRob Clark 	list_del(&obj->head);
813a4370c77SVille Syrjälä 	obj->funcs->atomic_destroy_state(obj, obj->state);
814b962a120SRob Clark 	drm_modeset_lock_fini(&obj->lock);
815a4370c77SVille Syrjälä }
816a4370c77SVille Syrjälä EXPORT_SYMBOL(drm_atomic_private_obj_fini);
817a4370c77SVille Syrjälä 
818a4370c77SVille Syrjälä /**
819b430c27aSPandiyan, Dhinakaran  * drm_atomic_get_private_obj_state - get private object state
820b430c27aSPandiyan, Dhinakaran  * @state: global atomic state
821b430c27aSPandiyan, Dhinakaran  * @obj: private object to get the state for
822b430c27aSPandiyan, Dhinakaran  *
823b430c27aSPandiyan, Dhinakaran  * This function returns the private object state for the given private object,
824b962a120SRob Clark  * allocating the state if needed. It will also grab the relevant private
825b962a120SRob Clark  * object lock to make sure that the state is consistent.
826b430c27aSPandiyan, Dhinakaran  *
827b430c27aSPandiyan, Dhinakaran  * RETURNS:
828b430c27aSPandiyan, Dhinakaran  * Either the allocated state or the error code encoded into a pointer.
829b430c27aSPandiyan, Dhinakaran  */
830a4370c77SVille Syrjälä struct drm_private_state *
drm_atomic_get_private_obj_state(struct drm_atomic_state * state,struct drm_private_obj * obj)831a4370c77SVille Syrjälä drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
832a4370c77SVille Syrjälä 				 struct drm_private_obj *obj)
833b430c27aSPandiyan, Dhinakaran {
834b962a120SRob Clark 	int index, num_objs, i, ret;
835b430c27aSPandiyan, Dhinakaran 	size_t size;
836b430c27aSPandiyan, Dhinakaran 	struct __drm_private_objs_state *arr;
837a4370c77SVille Syrjälä 	struct drm_private_state *obj_state;
838b430c27aSPandiyan, Dhinakaran 
839b430c27aSPandiyan, Dhinakaran 	for (i = 0; i < state->num_private_objs; i++)
840a4370c77SVille Syrjälä 		if (obj == state->private_objs[i].ptr)
841a4370c77SVille Syrjälä 			return state->private_objs[i].state;
842b430c27aSPandiyan, Dhinakaran 
843b962a120SRob Clark 	ret = drm_modeset_lock(&obj->lock, state->acquire_ctx);
844b962a120SRob Clark 	if (ret)
845b962a120SRob Clark 		return ERR_PTR(ret);
846b962a120SRob Clark 
847b430c27aSPandiyan, Dhinakaran 	num_objs = state->num_private_objs + 1;
848b430c27aSPandiyan, Dhinakaran 	size = sizeof(*state->private_objs) * num_objs;
849b430c27aSPandiyan, Dhinakaran 	arr = krealloc(state->private_objs, size, GFP_KERNEL);
850b430c27aSPandiyan, Dhinakaran 	if (!arr)
851b430c27aSPandiyan, Dhinakaran 		return ERR_PTR(-ENOMEM);
852b430c27aSPandiyan, Dhinakaran 
853b430c27aSPandiyan, Dhinakaran 	state->private_objs = arr;
854b430c27aSPandiyan, Dhinakaran 	index = state->num_private_objs;
855b430c27aSPandiyan, Dhinakaran 	memset(&state->private_objs[index], 0, sizeof(*state->private_objs));
856b430c27aSPandiyan, Dhinakaran 
857a4370c77SVille Syrjälä 	obj_state = obj->funcs->atomic_duplicate_state(obj);
858a4370c77SVille Syrjälä 	if (!obj_state)
859b430c27aSPandiyan, Dhinakaran 		return ERR_PTR(-ENOMEM);
860b430c27aSPandiyan, Dhinakaran 
861a4370c77SVille Syrjälä 	state->private_objs[index].state = obj_state;
862a4370c77SVille Syrjälä 	state->private_objs[index].old_state = obj->state;
863a4370c77SVille Syrjälä 	state->private_objs[index].new_state = obj_state;
864a4370c77SVille Syrjälä 	state->private_objs[index].ptr = obj;
865e89ea355SAlexandru Gheorghe 	obj_state->state = state;
866a4370c77SVille Syrjälä 
867b430c27aSPandiyan, Dhinakaran 	state->num_private_objs = num_objs;
868b430c27aSPandiyan, Dhinakaran 
8696e22dc35SClaudio Suarez 	drm_dbg_atomic(state->dev,
8706e22dc35SClaudio Suarez 		       "Added new private object %p state %p to %p\n",
871a4370c77SVille Syrjälä 		       obj, obj_state, state);
872b430c27aSPandiyan, Dhinakaran 
873a4370c77SVille Syrjälä 	return obj_state;
874b430c27aSPandiyan, Dhinakaran }
875b430c27aSPandiyan, Dhinakaran EXPORT_SYMBOL(drm_atomic_get_private_obj_state);
876b430c27aSPandiyan, Dhinakaran 
877b430c27aSPandiyan, Dhinakaran /**
8789801a7eaSjames qian wang (Arm Technology China)  * drm_atomic_get_old_private_obj_state
8799801a7eaSjames qian wang (Arm Technology China)  * @state: global atomic state object
8809801a7eaSjames qian wang (Arm Technology China)  * @obj: private_obj to grab
8819801a7eaSjames qian wang (Arm Technology China)  *
8829801a7eaSjames qian wang (Arm Technology China)  * This function returns the old private object state for the given private_obj,
8839801a7eaSjames qian wang (Arm Technology China)  * or NULL if the private_obj is not part of the global atomic state.
8849801a7eaSjames qian wang (Arm Technology China)  */
8859801a7eaSjames qian wang (Arm Technology China) struct drm_private_state *
drm_atomic_get_old_private_obj_state(const struct drm_atomic_state * state,struct drm_private_obj * obj)8862081bd89SMaxime Ripard drm_atomic_get_old_private_obj_state(const struct drm_atomic_state *state,
8879801a7eaSjames qian wang (Arm Technology China) 				     struct drm_private_obj *obj)
8889801a7eaSjames qian wang (Arm Technology China) {
8899801a7eaSjames qian wang (Arm Technology China) 	int i;
8909801a7eaSjames qian wang (Arm Technology China) 
8919801a7eaSjames qian wang (Arm Technology China) 	for (i = 0; i < state->num_private_objs; i++)
8929801a7eaSjames qian wang (Arm Technology China) 		if (obj == state->private_objs[i].ptr)
8939801a7eaSjames qian wang (Arm Technology China) 			return state->private_objs[i].old_state;
8949801a7eaSjames qian wang (Arm Technology China) 
8959801a7eaSjames qian wang (Arm Technology China) 	return NULL;
8969801a7eaSjames qian wang (Arm Technology China) }
8979801a7eaSjames qian wang (Arm Technology China) EXPORT_SYMBOL(drm_atomic_get_old_private_obj_state);
8989801a7eaSjames qian wang (Arm Technology China) 
8999801a7eaSjames qian wang (Arm Technology China) /**
9009801a7eaSjames qian wang (Arm Technology China)  * drm_atomic_get_new_private_obj_state
9019801a7eaSjames qian wang (Arm Technology China)  * @state: global atomic state object
9029801a7eaSjames qian wang (Arm Technology China)  * @obj: private_obj to grab
9039801a7eaSjames qian wang (Arm Technology China)  *
9049801a7eaSjames qian wang (Arm Technology China)  * This function returns the new private object state for the given private_obj,
9059801a7eaSjames qian wang (Arm Technology China)  * or NULL if the private_obj is not part of the global atomic state.
9069801a7eaSjames qian wang (Arm Technology China)  */
9079801a7eaSjames qian wang (Arm Technology China) struct drm_private_state *
drm_atomic_get_new_private_obj_state(const struct drm_atomic_state * state,struct drm_private_obj * obj)9082081bd89SMaxime Ripard drm_atomic_get_new_private_obj_state(const struct drm_atomic_state *state,
9099801a7eaSjames qian wang (Arm Technology China) 				     struct drm_private_obj *obj)
9109801a7eaSjames qian wang (Arm Technology China) {
9119801a7eaSjames qian wang (Arm Technology China) 	int i;
9129801a7eaSjames qian wang (Arm Technology China) 
9139801a7eaSjames qian wang (Arm Technology China) 	for (i = 0; i < state->num_private_objs; i++)
9149801a7eaSjames qian wang (Arm Technology China) 		if (obj == state->private_objs[i].ptr)
9159801a7eaSjames qian wang (Arm Technology China) 			return state->private_objs[i].new_state;
9169801a7eaSjames qian wang (Arm Technology China) 
9179801a7eaSjames qian wang (Arm Technology China) 	return NULL;
9189801a7eaSjames qian wang (Arm Technology China) }
9199801a7eaSjames qian wang (Arm Technology China) EXPORT_SYMBOL(drm_atomic_get_new_private_obj_state);
9209801a7eaSjames qian wang (Arm Technology China) 
9219801a7eaSjames qian wang (Arm Technology China) /**
9221b27fbddSLaurent Pinchart  * drm_atomic_get_old_connector_for_encoder - Get old connector for an encoder
9231b27fbddSLaurent Pinchart  * @state: Atomic state
9241b27fbddSLaurent Pinchart  * @encoder: The encoder to fetch the connector state for
9251b27fbddSLaurent Pinchart  *
9261b27fbddSLaurent Pinchart  * This function finds and returns the connector that was connected to @encoder
9271b27fbddSLaurent Pinchart  * as specified by the @state.
9281b27fbddSLaurent Pinchart  *
9291b27fbddSLaurent Pinchart  * If there is no connector in @state which previously had @encoder connected to
9301b27fbddSLaurent Pinchart  * it, this function will return NULL. While this may seem like an invalid use
9311b27fbddSLaurent Pinchart  * case, it is sometimes useful to differentiate commits which had no prior
9321b27fbddSLaurent Pinchart  * connectors attached to @encoder vs ones that did (and to inspect their
9331b27fbddSLaurent Pinchart  * state). This is especially true in enable hooks because the pipeline has
9341b27fbddSLaurent Pinchart  * changed.
9351b27fbddSLaurent Pinchart  *
9361b27fbddSLaurent Pinchart  * Returns: The old connector connected to @encoder, or NULL if the encoder is
9371b27fbddSLaurent Pinchart  * not connected.
9381b27fbddSLaurent Pinchart  */
9391b27fbddSLaurent Pinchart struct drm_connector *
drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state * state,struct drm_encoder * encoder)9402081bd89SMaxime Ripard drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state *state,
9411b27fbddSLaurent Pinchart 					 struct drm_encoder *encoder)
9421b27fbddSLaurent Pinchart {
9431b27fbddSLaurent Pinchart 	struct drm_connector_state *conn_state;
9441b27fbddSLaurent Pinchart 	struct drm_connector *connector;
9451b27fbddSLaurent Pinchart 	unsigned int i;
9461b27fbddSLaurent Pinchart 
9471b27fbddSLaurent Pinchart 	for_each_old_connector_in_state(state, connector, conn_state, i) {
9481b27fbddSLaurent Pinchart 		if (conn_state->best_encoder == encoder)
9491b27fbddSLaurent Pinchart 			return connector;
9501b27fbddSLaurent Pinchart 	}
9511b27fbddSLaurent Pinchart 
9521b27fbddSLaurent Pinchart 	return NULL;
9531b27fbddSLaurent Pinchart }
9541b27fbddSLaurent Pinchart EXPORT_SYMBOL(drm_atomic_get_old_connector_for_encoder);
9551b27fbddSLaurent Pinchart 
9561b27fbddSLaurent Pinchart /**
9571b27fbddSLaurent Pinchart  * drm_atomic_get_new_connector_for_encoder - Get new connector for an encoder
9581b27fbddSLaurent Pinchart  * @state: Atomic state
9591b27fbddSLaurent Pinchart  * @encoder: The encoder to fetch the connector state for
9601b27fbddSLaurent Pinchart  *
9611b27fbddSLaurent Pinchart  * This function finds and returns the connector that will be connected to
9621b27fbddSLaurent Pinchart  * @encoder as specified by the @state.
9631b27fbddSLaurent Pinchart  *
9641b27fbddSLaurent Pinchart  * If there is no connector in @state which will have @encoder connected to it,
9651b27fbddSLaurent Pinchart  * this function will return NULL. While this may seem like an invalid use case,
9661b27fbddSLaurent Pinchart  * it is sometimes useful to differentiate commits which have no connectors
9671b27fbddSLaurent Pinchart  * attached to @encoder vs ones that do (and to inspect their state). This is
9681b27fbddSLaurent Pinchart  * especially true in disable hooks because the pipeline will change.
9691b27fbddSLaurent Pinchart  *
9701b27fbddSLaurent Pinchart  * Returns: The new connector connected to @encoder, or NULL if the encoder is
9711b27fbddSLaurent Pinchart  * not connected.
9721b27fbddSLaurent Pinchart  */
9731b27fbddSLaurent Pinchart struct drm_connector *
drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state * state,struct drm_encoder * encoder)9742081bd89SMaxime Ripard drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state,
9751b27fbddSLaurent Pinchart 					 struct drm_encoder *encoder)
9761b27fbddSLaurent Pinchart {
9771b27fbddSLaurent Pinchart 	struct drm_connector_state *conn_state;
9781b27fbddSLaurent Pinchart 	struct drm_connector *connector;
9791b27fbddSLaurent Pinchart 	unsigned int i;
9801b27fbddSLaurent Pinchart 
9811b27fbddSLaurent Pinchart 	for_each_new_connector_in_state(state, connector, conn_state, i) {
9821b27fbddSLaurent Pinchart 		if (conn_state->best_encoder == encoder)
9831b27fbddSLaurent Pinchart 			return connector;
9841b27fbddSLaurent Pinchart 	}
9851b27fbddSLaurent Pinchart 
9861b27fbddSLaurent Pinchart 	return NULL;
9871b27fbddSLaurent Pinchart }
9881b27fbddSLaurent Pinchart EXPORT_SYMBOL(drm_atomic_get_new_connector_for_encoder);
9891b27fbddSLaurent Pinchart 
9901b27fbddSLaurent Pinchart /**
9917b9a9e35SVinod Polimera  * drm_atomic_get_old_crtc_for_encoder - Get old crtc for an encoder
9927b9a9e35SVinod Polimera  * @state: Atomic state
9937b9a9e35SVinod Polimera  * @encoder: The encoder to fetch the crtc state for
9947b9a9e35SVinod Polimera  *
9957b9a9e35SVinod Polimera  * This function finds and returns the crtc that was connected to @encoder
9967b9a9e35SVinod Polimera  * as specified by the @state.
9977b9a9e35SVinod Polimera  *
9987b9a9e35SVinod Polimera  * Returns: The old crtc connected to @encoder, or NULL if the encoder is
9997b9a9e35SVinod Polimera  * not connected.
10007b9a9e35SVinod Polimera  */
10017b9a9e35SVinod Polimera struct drm_crtc *
drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state * state,struct drm_encoder * encoder)10027b9a9e35SVinod Polimera drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state,
10037b9a9e35SVinod Polimera 				    struct drm_encoder *encoder)
10047b9a9e35SVinod Polimera {
10057b9a9e35SVinod Polimera 	struct drm_connector *connector;
10067b9a9e35SVinod Polimera 	struct drm_connector_state *conn_state;
10077b9a9e35SVinod Polimera 
10087b9a9e35SVinod Polimera 	connector = drm_atomic_get_old_connector_for_encoder(state, encoder);
10097b9a9e35SVinod Polimera 	if (!connector)
10107b9a9e35SVinod Polimera 		return NULL;
10117b9a9e35SVinod Polimera 
10127b9a9e35SVinod Polimera 	conn_state = drm_atomic_get_old_connector_state(state, connector);
10137b9a9e35SVinod Polimera 	if (!conn_state)
10147b9a9e35SVinod Polimera 		return NULL;
10157b9a9e35SVinod Polimera 
10167b9a9e35SVinod Polimera 	return conn_state->crtc;
10177b9a9e35SVinod Polimera }
10187b9a9e35SVinod Polimera EXPORT_SYMBOL(drm_atomic_get_old_crtc_for_encoder);
10197b9a9e35SVinod Polimera 
10207b9a9e35SVinod Polimera /**
10217b9a9e35SVinod Polimera  * drm_atomic_get_new_crtc_for_encoder - Get new crtc for an encoder
10227b9a9e35SVinod Polimera  * @state: Atomic state
10237b9a9e35SVinod Polimera  * @encoder: The encoder to fetch the crtc state for
10247b9a9e35SVinod Polimera  *
10257b9a9e35SVinod Polimera  * This function finds and returns the crtc that will be connected to @encoder
10267b9a9e35SVinod Polimera  * as specified by the @state.
10277b9a9e35SVinod Polimera  *
10287b9a9e35SVinod Polimera  * Returns: The new crtc connected to @encoder, or NULL if the encoder is
10297b9a9e35SVinod Polimera  * not connected.
10307b9a9e35SVinod Polimera  */
10317b9a9e35SVinod Polimera struct drm_crtc *
drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state * state,struct drm_encoder * encoder)10327b9a9e35SVinod Polimera drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state,
10337b9a9e35SVinod Polimera 				    struct drm_encoder *encoder)
10347b9a9e35SVinod Polimera {
10357b9a9e35SVinod Polimera 	struct drm_connector *connector;
10367b9a9e35SVinod Polimera 	struct drm_connector_state *conn_state;
10377b9a9e35SVinod Polimera 
10387b9a9e35SVinod Polimera 	connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
10397b9a9e35SVinod Polimera 	if (!connector)
10407b9a9e35SVinod Polimera 		return NULL;
10417b9a9e35SVinod Polimera 
10427b9a9e35SVinod Polimera 	conn_state = drm_atomic_get_new_connector_state(state, connector);
10437b9a9e35SVinod Polimera 	if (!conn_state)
10447b9a9e35SVinod Polimera 		return NULL;
10457b9a9e35SVinod Polimera 
10467b9a9e35SVinod Polimera 	return conn_state->crtc;
10477b9a9e35SVinod Polimera }
10487b9a9e35SVinod Polimera EXPORT_SYMBOL(drm_atomic_get_new_crtc_for_encoder);
10497b9a9e35SVinod Polimera 
10507b9a9e35SVinod Polimera /**
1051cc4ceb48SDaniel Vetter  * drm_atomic_get_connector_state - get connector state
1052cc4ceb48SDaniel Vetter  * @state: global atomic state object
1053cc4ceb48SDaniel Vetter  * @connector: connector to get state object for
1054cc4ceb48SDaniel Vetter  *
1055cc4ceb48SDaniel Vetter  * This function returns the connector state for the given connector,
1056cc4ceb48SDaniel Vetter  * allocating it if needed. It will also grab the relevant connector lock to
1057cc4ceb48SDaniel Vetter  * make sure that the state is consistent.
1058cc4ceb48SDaniel Vetter  *
1059cc4ceb48SDaniel Vetter  * Returns:
1060cc4ceb48SDaniel Vetter  * Either the allocated state or the error code encoded into the pointer. When
1061cc4ceb48SDaniel Vetter  * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
1062cc4ceb48SDaniel Vetter  * entire atomic sequence must be restarted. All other errors are fatal.
1063cc4ceb48SDaniel Vetter  */
1064cc4ceb48SDaniel Vetter struct drm_connector_state *
drm_atomic_get_connector_state(struct drm_atomic_state * state,struct drm_connector * connector)1065cc4ceb48SDaniel Vetter drm_atomic_get_connector_state(struct drm_atomic_state *state,
1066cc4ceb48SDaniel Vetter 			  struct drm_connector *connector)
1067cc4ceb48SDaniel Vetter {
1068cc4ceb48SDaniel Vetter 	int ret, index;
1069cc4ceb48SDaniel Vetter 	struct drm_mode_config *config = &connector->dev->mode_config;
1070cc4ceb48SDaniel Vetter 	struct drm_connector_state *connector_state;
1071cc4ceb48SDaniel Vetter 
10727f4eaa89SMaarten Lankhorst 	WARN_ON(!state->acquire_ctx);
10737f4eaa89SMaarten Lankhorst 
1074c7eb76f4SDaniel Vetter 	ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
1075c7eb76f4SDaniel Vetter 	if (ret)
1076c7eb76f4SDaniel Vetter 		return ERR_PTR(ret);
1077c7eb76f4SDaniel Vetter 
1078cc4ceb48SDaniel Vetter 	index = drm_connector_index(connector);
1079cc4ceb48SDaniel Vetter 
1080f52b69f1SDaniel Vetter 	if (index >= state->num_connector) {
108163e83c1dSDaniel Vetter 		struct __drm_connnectors_state *c;
10825fff80bbSMaarten Lankhorst 		int alloc = max(index + 1, config->num_connector);
10835fff80bbSMaarten Lankhorst 
108432ce2553SBartosz Golaszewski 		c = krealloc_array(state->connectors, alloc,
108532ce2553SBartosz Golaszewski 				   sizeof(*state->connectors), GFP_KERNEL);
10865fff80bbSMaarten Lankhorst 		if (!c)
10875fff80bbSMaarten Lankhorst 			return ERR_PTR(-ENOMEM);
10885fff80bbSMaarten Lankhorst 
10895fff80bbSMaarten Lankhorst 		state->connectors = c;
10905fff80bbSMaarten Lankhorst 		memset(&state->connectors[state->num_connector], 0,
10915fff80bbSMaarten Lankhorst 		       sizeof(*state->connectors) * (alloc - state->num_connector));
10925fff80bbSMaarten Lankhorst 
10935fff80bbSMaarten Lankhorst 		state->num_connector = alloc;
1094f52b69f1SDaniel Vetter 	}
1095f52b69f1SDaniel Vetter 
109663e83c1dSDaniel Vetter 	if (state->connectors[index].state)
109763e83c1dSDaniel Vetter 		return state->connectors[index].state;
1098cc4ceb48SDaniel Vetter 
1099cc4ceb48SDaniel Vetter 	connector_state = connector->funcs->atomic_duplicate_state(connector);
1100cc4ceb48SDaniel Vetter 	if (!connector_state)
1101cc4ceb48SDaniel Vetter 		return ERR_PTR(-ENOMEM);
1102cc4ceb48SDaniel Vetter 
1103ad093607SThierry Reding 	drm_connector_get(connector);
110463e83c1dSDaniel Vetter 	state->connectors[index].state = connector_state;
1105581e49feSMaarten Lankhorst 	state->connectors[index].old_state = connector->state;
1106581e49feSMaarten Lankhorst 	state->connectors[index].new_state = connector_state;
110763e83c1dSDaniel Vetter 	state->connectors[index].ptr = connector;
1108cc4ceb48SDaniel Vetter 	connector_state->state = state;
1109cc4ceb48SDaniel Vetter 
11106e22dc35SClaudio Suarez 	drm_dbg_atomic(connector->dev, "Added [CONNECTOR:%d:%s] %p state to %p\n",
11116ac7c548SRussell King 			 connector->base.id, connector->name,
11126ac7c548SRussell King 			 connector_state, state);
1113cc4ceb48SDaniel Vetter 
1114cc4ceb48SDaniel Vetter 	if (connector_state->crtc) {
1115cc4ceb48SDaniel Vetter 		struct drm_crtc_state *crtc_state;
1116cc4ceb48SDaniel Vetter 
1117cc4ceb48SDaniel Vetter 		crtc_state = drm_atomic_get_crtc_state(state,
1118cc4ceb48SDaniel Vetter 						       connector_state->crtc);
1119cc4ceb48SDaniel Vetter 		if (IS_ERR(crtc_state))
1120cc4ceb48SDaniel Vetter 			return ERR_CAST(crtc_state);
1121cc4ceb48SDaniel Vetter 	}
1122cc4ceb48SDaniel Vetter 
1123cc4ceb48SDaniel Vetter 	return connector_state;
1124cc4ceb48SDaniel Vetter }
1125cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_get_connector_state);
1126cc4ceb48SDaniel Vetter 
drm_atomic_connector_print_state(struct drm_printer * p,const struct drm_connector_state * state)1127fceffb32SRob Clark static void drm_atomic_connector_print_state(struct drm_printer *p,
1128fceffb32SRob Clark 		const struct drm_connector_state *state)
1129fceffb32SRob Clark {
1130fceffb32SRob Clark 	struct drm_connector *connector = state->connector;
1131fceffb32SRob Clark 
1132fceffb32SRob Clark 	drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);
1133fceffb32SRob Clark 	drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
11341452c25bSSean Paul 	drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware);
11357d386975SHarry Wentland 	drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
1136035d53e0SHarry Wentland 	drm_printf(p, "\tcolorspace=%s\n", drm_get_colorspace_name(state->colorspace));
1137fceffb32SRob Clark 
1138aadb3e16SMaxime Ripard 	if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
1139aadb3e16SMaxime Ripard 	    connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
1140ab52af4bSMaxime Ripard 		drm_printf(p, "\tbroadcast_rgb=%s\n",
1141ab52af4bSMaxime Ripard 			   drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
1142027d4359SMaxime Ripard 		drm_printf(p, "\tis_limited_range=%c\n", state->hdmi.is_limited_range ? 'y' : 'n');
1143aadb3e16SMaxime Ripard 		drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
1144948f01d5SMaxime Ripard 		drm_printf(p, "\toutput_format=%s\n",
1145948f01d5SMaxime Ripard 			   drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
1146f035f409SMaxime Ripard 		drm_printf(p, "\ttmds_char_rate=%llu\n", state->hdmi.tmds_char_rate);
1147aadb3e16SMaxime Ripard 	}
1148aadb3e16SMaxime Ripard 
11498cbc5cafSBrian Starkey 	if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
11508cbc5cafSBrian Starkey 		if (state->writeback_job && state->writeback_job->fb)
11518cbc5cafSBrian Starkey 			drm_printf(p, "\tfb=%d\n", state->writeback_job->fb->base.id);
11528cbc5cafSBrian Starkey 
1153fceffb32SRob Clark 	if (connector->funcs->atomic_print_state)
1154fceffb32SRob Clark 		connector->funcs->atomic_print_state(p, state);
1155fceffb32SRob Clark }
1156fceffb32SRob Clark 
1157cc4ceb48SDaniel Vetter /**
115875146591SBoris Brezillon  * drm_atomic_get_bridge_state - get bridge state
115975146591SBoris Brezillon  * @state: global atomic state object
116075146591SBoris Brezillon  * @bridge: bridge to get state object for
116175146591SBoris Brezillon  *
116275146591SBoris Brezillon  * This function returns the bridge state for the given bridge, allocating it
116375146591SBoris Brezillon  * if needed. It will also grab the relevant bridge lock to make sure that the
116475146591SBoris Brezillon  * state is consistent.
116575146591SBoris Brezillon  *
116675146591SBoris Brezillon  * Returns:
116775146591SBoris Brezillon  * Either the allocated state or the error code encoded into the pointer. When
116875146591SBoris Brezillon  * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
116975146591SBoris Brezillon  * entire atomic sequence must be restarted.
117075146591SBoris Brezillon  */
117175146591SBoris Brezillon struct drm_bridge_state *
drm_atomic_get_bridge_state(struct drm_atomic_state * state,struct drm_bridge * bridge)117275146591SBoris Brezillon drm_atomic_get_bridge_state(struct drm_atomic_state *state,
117375146591SBoris Brezillon 			    struct drm_bridge *bridge)
117475146591SBoris Brezillon {
117575146591SBoris Brezillon 	struct drm_private_state *obj_state;
117675146591SBoris Brezillon 
117775146591SBoris Brezillon 	obj_state = drm_atomic_get_private_obj_state(state, &bridge->base);
117875146591SBoris Brezillon 	if (IS_ERR(obj_state))
117975146591SBoris Brezillon 		return ERR_CAST(obj_state);
118075146591SBoris Brezillon 
118175146591SBoris Brezillon 	return drm_priv_to_bridge_state(obj_state);
118275146591SBoris Brezillon }
118375146591SBoris Brezillon EXPORT_SYMBOL(drm_atomic_get_bridge_state);
118475146591SBoris Brezillon 
118575146591SBoris Brezillon /**
118675146591SBoris Brezillon  * drm_atomic_get_old_bridge_state - get old bridge state, if it exists
118775146591SBoris Brezillon  * @state: global atomic state object
118875146591SBoris Brezillon  * @bridge: bridge to grab
118975146591SBoris Brezillon  *
119075146591SBoris Brezillon  * This function returns the old bridge state for the given bridge, or NULL if
119175146591SBoris Brezillon  * the bridge is not part of the global atomic state.
119275146591SBoris Brezillon  */
119375146591SBoris Brezillon struct drm_bridge_state *
drm_atomic_get_old_bridge_state(const struct drm_atomic_state * state,struct drm_bridge * bridge)11942081bd89SMaxime Ripard drm_atomic_get_old_bridge_state(const struct drm_atomic_state *state,
119575146591SBoris Brezillon 				struct drm_bridge *bridge)
119675146591SBoris Brezillon {
119775146591SBoris Brezillon 	struct drm_private_state *obj_state;
119875146591SBoris Brezillon 
119975146591SBoris Brezillon 	obj_state = drm_atomic_get_old_private_obj_state(state, &bridge->base);
120075146591SBoris Brezillon 	if (!obj_state)
120175146591SBoris Brezillon 		return NULL;
120275146591SBoris Brezillon 
120375146591SBoris Brezillon 	return drm_priv_to_bridge_state(obj_state);
120475146591SBoris Brezillon }
120575146591SBoris Brezillon EXPORT_SYMBOL(drm_atomic_get_old_bridge_state);
120675146591SBoris Brezillon 
120775146591SBoris Brezillon /**
120875146591SBoris Brezillon  * drm_atomic_get_new_bridge_state - get new bridge state, if it exists
120975146591SBoris Brezillon  * @state: global atomic state object
121075146591SBoris Brezillon  * @bridge: bridge to grab
121175146591SBoris Brezillon  *
121275146591SBoris Brezillon  * This function returns the new bridge state for the given bridge, or NULL if
121375146591SBoris Brezillon  * the bridge is not part of the global atomic state.
121475146591SBoris Brezillon  */
121575146591SBoris Brezillon struct drm_bridge_state *
drm_atomic_get_new_bridge_state(const struct drm_atomic_state * state,struct drm_bridge * bridge)12162081bd89SMaxime Ripard drm_atomic_get_new_bridge_state(const struct drm_atomic_state *state,
121775146591SBoris Brezillon 				struct drm_bridge *bridge)
121875146591SBoris Brezillon {
121975146591SBoris Brezillon 	struct drm_private_state *obj_state;
122075146591SBoris Brezillon 
122175146591SBoris Brezillon 	obj_state = drm_atomic_get_new_private_obj_state(state, &bridge->base);
122275146591SBoris Brezillon 	if (!obj_state)
122375146591SBoris Brezillon 		return NULL;
122475146591SBoris Brezillon 
122575146591SBoris Brezillon 	return drm_priv_to_bridge_state(obj_state);
122675146591SBoris Brezillon }
122775146591SBoris Brezillon EXPORT_SYMBOL(drm_atomic_get_new_bridge_state);
122875146591SBoris Brezillon 
122975146591SBoris Brezillon /**
123075146591SBoris Brezillon  * drm_atomic_add_encoder_bridges - add bridges attached to an encoder
123175146591SBoris Brezillon  * @state: atomic state
123275146591SBoris Brezillon  * @encoder: DRM encoder
123375146591SBoris Brezillon  *
123475146591SBoris Brezillon  * This function adds all bridges attached to @encoder. This is needed to add
123575146591SBoris Brezillon  * bridge states to @state and make them available when
123691ea8330SBoris Brezillon  * &drm_bridge_funcs.atomic_check(), &drm_bridge_funcs.atomic_pre_enable(),
123791ea8330SBoris Brezillon  * &drm_bridge_funcs.atomic_enable(),
123891ea8330SBoris Brezillon  * &drm_bridge_funcs.atomic_disable_post_disable() are called.
123975146591SBoris Brezillon  *
124075146591SBoris Brezillon  * Returns:
124175146591SBoris Brezillon  * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
124275146591SBoris Brezillon  * then the w/w mutex code has detected a deadlock and the entire atomic
124375146591SBoris Brezillon  * sequence must be restarted. All other errors are fatal.
124475146591SBoris Brezillon  */
124575146591SBoris Brezillon int
drm_atomic_add_encoder_bridges(struct drm_atomic_state * state,struct drm_encoder * encoder)124675146591SBoris Brezillon drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
124775146591SBoris Brezillon 			       struct drm_encoder *encoder)
124875146591SBoris Brezillon {
124975146591SBoris Brezillon 	struct drm_bridge_state *bridge_state;
125075146591SBoris Brezillon 	struct drm_bridge *bridge;
125175146591SBoris Brezillon 
125275146591SBoris Brezillon 	if (!encoder)
125375146591SBoris Brezillon 		return 0;
125475146591SBoris Brezillon 
12556e22dc35SClaudio Suarez 	drm_dbg_atomic(encoder->dev,
12566e22dc35SClaudio Suarez 		       "Adding all bridges for [encoder:%d:%s] to %p\n",
125775146591SBoris Brezillon 		       encoder->base.id, encoder->name, state);
125875146591SBoris Brezillon 
125975146591SBoris Brezillon 	drm_for_each_bridge_in_chain(encoder, bridge) {
126075146591SBoris Brezillon 		/* Skip bridges that don't implement the atomic state hooks. */
126175146591SBoris Brezillon 		if (!bridge->funcs->atomic_duplicate_state)
126275146591SBoris Brezillon 			continue;
126375146591SBoris Brezillon 
126475146591SBoris Brezillon 		bridge_state = drm_atomic_get_bridge_state(state, bridge);
126575146591SBoris Brezillon 		if (IS_ERR(bridge_state))
126675146591SBoris Brezillon 			return PTR_ERR(bridge_state);
126775146591SBoris Brezillon 	}
126875146591SBoris Brezillon 
126975146591SBoris Brezillon 	return 0;
127075146591SBoris Brezillon }
127175146591SBoris Brezillon EXPORT_SYMBOL(drm_atomic_add_encoder_bridges);
127275146591SBoris Brezillon 
127375146591SBoris Brezillon /**
127442240c90SThierry Reding  * drm_atomic_add_affected_connectors - add connectors for CRTC
1275cc4ceb48SDaniel Vetter  * @state: atomic state
127642240c90SThierry Reding  * @crtc: DRM CRTC
1277cc4ceb48SDaniel Vetter  *
1278cc4ceb48SDaniel Vetter  * This function walks the current configuration and adds all connectors
1279cc4ceb48SDaniel Vetter  * currently using @crtc to the atomic configuration @state. Note that this
1280cc4ceb48SDaniel Vetter  * function must acquire the connection mutex. This can potentially cause
1281a8a1de90SBhaskar Chowdhury  * unneeded serialization if the update is just for the planes on one CRTC. Hence
1282cc4ceb48SDaniel Vetter  * drivers and helpers should only call this when really needed (e.g. when a
1283cc4ceb48SDaniel Vetter  * full modeset needs to happen due to some change).
1284cc4ceb48SDaniel Vetter  *
1285cc4ceb48SDaniel Vetter  * Returns:
1286cc4ceb48SDaniel Vetter  * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
1287cc4ceb48SDaniel Vetter  * then the w/w mutex code has detected a deadlock and the entire atomic
1288cc4ceb48SDaniel Vetter  * sequence must be restarted. All other errors are fatal.
1289cc4ceb48SDaniel Vetter  */
1290cc4ceb48SDaniel Vetter int
drm_atomic_add_affected_connectors(struct drm_atomic_state * state,struct drm_crtc * crtc)1291cc4ceb48SDaniel Vetter drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
1292cc4ceb48SDaniel Vetter 				   struct drm_crtc *crtc)
1293cc4ceb48SDaniel Vetter {
1294cc4ceb48SDaniel Vetter 	struct drm_mode_config *config = &state->dev->mode_config;
1295cc4ceb48SDaniel Vetter 	struct drm_connector *connector;
1296cc4ceb48SDaniel Vetter 	struct drm_connector_state *conn_state;
1297613051daSDaniel Vetter 	struct drm_connector_list_iter conn_iter;
12985351bbddSMaarten Lankhorst 	struct drm_crtc_state *crtc_state;
1299cc4ceb48SDaniel Vetter 	int ret;
1300cc4ceb48SDaniel Vetter 
13015351bbddSMaarten Lankhorst 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
13025351bbddSMaarten Lankhorst 	if (IS_ERR(crtc_state))
13035351bbddSMaarten Lankhorst 		return PTR_ERR(crtc_state);
13045351bbddSMaarten Lankhorst 
1305cc4ceb48SDaniel Vetter 	ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
1306cc4ceb48SDaniel Vetter 	if (ret)
1307cc4ceb48SDaniel Vetter 		return ret;
1308cc4ceb48SDaniel Vetter 
13096e22dc35SClaudio Suarez 	drm_dbg_atomic(crtc->dev,
13106e22dc35SClaudio Suarez 		       "Adding all current connectors for [CRTC:%d:%s] to %p\n",
1311fa3ab4c2SVille Syrjälä 		       crtc->base.id, crtc->name, state);
1312cc4ceb48SDaniel Vetter 
1313cc4ceb48SDaniel Vetter 	/*
13145351bbddSMaarten Lankhorst 	 * Changed connectors are already in @state, so only need to look
13155351bbddSMaarten Lankhorst 	 * at the connector_mask in crtc_state.
1316cc4ceb48SDaniel Vetter 	 */
1317b982dab1SThierry Reding 	drm_connector_list_iter_begin(state->dev, &conn_iter);
1318613051daSDaniel Vetter 	drm_for_each_connector_iter(connector, &conn_iter) {
131973705732SVille Syrjälä 		if (!(crtc_state->connector_mask & drm_connector_mask(connector)))
1320cc4ceb48SDaniel Vetter 			continue;
1321cc4ceb48SDaniel Vetter 
1322cc4ceb48SDaniel Vetter 		conn_state = drm_atomic_get_connector_state(state, connector);
1323613051daSDaniel Vetter 		if (IS_ERR(conn_state)) {
1324b982dab1SThierry Reding 			drm_connector_list_iter_end(&conn_iter);
1325cc4ceb48SDaniel Vetter 			return PTR_ERR(conn_state);
1326cc4ceb48SDaniel Vetter 		}
1327613051daSDaniel Vetter 	}
1328b982dab1SThierry Reding 	drm_connector_list_iter_end(&conn_iter);
1329cc4ceb48SDaniel Vetter 
1330cc4ceb48SDaniel Vetter 	return 0;
1331cc4ceb48SDaniel Vetter }
1332cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_add_affected_connectors);
1333cc4ceb48SDaniel Vetter 
1334cc4ceb48SDaniel Vetter /**
133542240c90SThierry Reding  * drm_atomic_add_affected_planes - add planes for CRTC
1336e01e9f75SMaarten Lankhorst  * @state: atomic state
133742240c90SThierry Reding  * @crtc: DRM CRTC
1338e01e9f75SMaarten Lankhorst  *
1339e01e9f75SMaarten Lankhorst  * This function walks the current configuration and adds all planes
1340e01e9f75SMaarten Lankhorst  * currently used by @crtc to the atomic configuration @state. This is useful
1341e01e9f75SMaarten Lankhorst  * when an atomic commit also needs to check all currently enabled plane on
1342e01e9f75SMaarten Lankhorst  * @crtc, e.g. when changing the mode. It's also useful when re-enabling a CRTC
1343e01e9f75SMaarten Lankhorst  * to avoid special code to force-enable all planes.
1344e01e9f75SMaarten Lankhorst  *
1345e01e9f75SMaarten Lankhorst  * Since acquiring a plane state will always also acquire the w/w mutex of the
1346e01e9f75SMaarten Lankhorst  * current CRTC for that plane (if there is any) adding all the plane states for
1347a8a1de90SBhaskar Chowdhury  * a CRTC will not reduce parallelism of atomic updates.
1348e01e9f75SMaarten Lankhorst  *
1349e01e9f75SMaarten Lankhorst  * Returns:
1350e01e9f75SMaarten Lankhorst  * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
1351e01e9f75SMaarten Lankhorst  * then the w/w mutex code has detected a deadlock and the entire atomic
1352e01e9f75SMaarten Lankhorst  * sequence must be restarted. All other errors are fatal.
1353e01e9f75SMaarten Lankhorst  */
1354e01e9f75SMaarten Lankhorst int
drm_atomic_add_affected_planes(struct drm_atomic_state * state,struct drm_crtc * crtc)1355e01e9f75SMaarten Lankhorst drm_atomic_add_affected_planes(struct drm_atomic_state *state,
1356e01e9f75SMaarten Lankhorst 			       struct drm_crtc *crtc)
1357e01e9f75SMaarten Lankhorst {
1358534903d6SVille Syrjälä 	const struct drm_crtc_state *old_crtc_state =
1359534903d6SVille Syrjälä 		drm_atomic_get_old_crtc_state(state, crtc);
1360e01e9f75SMaarten Lankhorst 	struct drm_plane *plane;
1361e01e9f75SMaarten Lankhorst 
1362b4d93679SMaarten Lankhorst 	WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
1363e01e9f75SMaarten Lankhorst 
13646e22dc35SClaudio Suarez 	drm_dbg_atomic(crtc->dev,
13656e22dc35SClaudio Suarez 		       "Adding all current planes for [CRTC:%d:%s] to %p\n",
1366b6f690abSVille Syrjälä 		       crtc->base.id, crtc->name, state);
1367b6f690abSVille Syrjälä 
1368534903d6SVille Syrjälä 	drm_for_each_plane_mask(plane, state->dev, old_crtc_state->plane_mask) {
1369e01e9f75SMaarten Lankhorst 		struct drm_plane_state *plane_state =
1370e01e9f75SMaarten Lankhorst 			drm_atomic_get_plane_state(state, plane);
1371e01e9f75SMaarten Lankhorst 
1372e01e9f75SMaarten Lankhorst 		if (IS_ERR(plane_state))
1373e01e9f75SMaarten Lankhorst 			return PTR_ERR(plane_state);
1374e01e9f75SMaarten Lankhorst 	}
1375e01e9f75SMaarten Lankhorst 	return 0;
1376e01e9f75SMaarten Lankhorst }
1377e01e9f75SMaarten Lankhorst EXPORT_SYMBOL(drm_atomic_add_affected_planes);
1378e01e9f75SMaarten Lankhorst 
1379e01e9f75SMaarten Lankhorst /**
1380cc4ceb48SDaniel Vetter  * drm_atomic_check_only - check whether a given config would work
1381cc4ceb48SDaniel Vetter  * @state: atomic configuration to check
1382cc4ceb48SDaniel Vetter  *
1383cc4ceb48SDaniel Vetter  * Note that this function can return -EDEADLK if the driver needed to acquire
1384cc4ceb48SDaniel Vetter  * more locks but encountered a deadlock. The caller must then do the usual w/w
1385cc4ceb48SDaniel Vetter  * backoff dance and restart. All other errors are fatal.
1386cc4ceb48SDaniel Vetter  *
1387cc4ceb48SDaniel Vetter  * Returns:
1388cc4ceb48SDaniel Vetter  * 0 on success, negative error code on failure.
1389cc4ceb48SDaniel Vetter  */
drm_atomic_check_only(struct drm_atomic_state * state)1390cc4ceb48SDaniel Vetter int drm_atomic_check_only(struct drm_atomic_state *state)
1391cc4ceb48SDaniel Vetter {
13925e743737SRob Clark 	struct drm_device *dev = state->dev;
13935e743737SRob Clark 	struct drm_mode_config *config = &dev->mode_config;
1394df63b999SAnder Conselvan de Oliveira 	struct drm_plane *plane;
1395d9be05b7SVille Syrjälä 	struct drm_plane_state *old_plane_state;
1396d9be05b7SVille Syrjälä 	struct drm_plane_state *new_plane_state;
1397df63b999SAnder Conselvan de Oliveira 	struct drm_crtc *crtc;
1398b2432adfSVille Syrjälä 	struct drm_crtc_state *old_crtc_state;
1399b2432adfSVille Syrjälä 	struct drm_crtc_state *new_crtc_state;
1400935774cdSBrian Starkey 	struct drm_connector *conn;
1401935774cdSBrian Starkey 	struct drm_connector_state *conn_state;
14021cdb005dSFabio M. De Francesco 	unsigned int requested_crtc = 0;
14031cdb005dSFabio M. De Francesco 	unsigned int affected_crtc = 0;
14045e743737SRob Clark 	int i, ret = 0;
1405cc4ceb48SDaniel Vetter 
14066e22dc35SClaudio Suarez 	drm_dbg_atomic(dev, "checking %p\n", state);
1407cc4ceb48SDaniel Vetter 
14085ec1cebdSManasi Navare 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
14095ec1cebdSManasi Navare 		if (new_crtc_state->enable)
1410fb6473a4SDaniel Vetter 			requested_crtc |= drm_crtc_mask(crtc);
14115ec1cebdSManasi Navare 	}
1412fb6473a4SDaniel Vetter 
1413d9be05b7SVille Syrjälä 	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
1414d9be05b7SVille Syrjälä 		ret = drm_atomic_plane_check(old_plane_state, new_plane_state);
14155e743737SRob Clark 		if (ret) {
14166e22dc35SClaudio Suarez 			drm_dbg_atomic(dev, "[PLANE:%d:%s] atomic core check failed\n",
14179f4c97a2SVille Syrjälä 				       plane->base.id, plane->name);
14185e743737SRob Clark 			return ret;
14195e743737SRob Clark 		}
14205e743737SRob Clark 	}
14215e743737SRob Clark 
1422b2432adfSVille Syrjälä 	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
1423b2432adfSVille Syrjälä 		ret = drm_atomic_crtc_check(old_crtc_state, new_crtc_state);
14245e743737SRob Clark 		if (ret) {
14256e22dc35SClaudio Suarez 			drm_dbg_atomic(dev, "[CRTC:%d:%s] atomic core check failed\n",
1426fa3ab4c2SVille Syrjälä 				       crtc->base.id, crtc->name);
14275e743737SRob Clark 			return ret;
14285e743737SRob Clark 		}
14295e743737SRob Clark 	}
14305e743737SRob Clark 
1431935774cdSBrian Starkey 	for_each_new_connector_in_state(state, conn, conn_state, i) {
1432935774cdSBrian Starkey 		ret = drm_atomic_connector_check(conn, conn_state);
1433935774cdSBrian Starkey 		if (ret) {
14346e22dc35SClaudio Suarez 			drm_dbg_atomic(dev, "[CONNECTOR:%d:%s] atomic core check failed\n",
1435935774cdSBrian Starkey 				       conn->base.id, conn->name);
1436935774cdSBrian Starkey 			return ret;
1437935774cdSBrian Starkey 		}
1438935774cdSBrian Starkey 	}
1439935774cdSBrian Starkey 
144014d4e522SLyude Paul 	if (config->funcs->atomic_check) {
14415e743737SRob Clark 		ret = config->funcs->atomic_check(state->dev, state);
14425e743737SRob Clark 
144314d4e522SLyude Paul 		if (ret) {
14446e22dc35SClaudio Suarez 			drm_dbg_atomic(dev, "atomic driver check for %p failed: %d\n",
144514d4e522SLyude Paul 				       state, ret);
1446a0ffc51eSMaarten Lankhorst 			return ret;
144714d4e522SLyude Paul 		}
144814d4e522SLyude Paul 	}
1449a0ffc51eSMaarten Lankhorst 
1450d34f20d6SRob Clark 	if (!state->allow_modeset) {
1451b2432adfSVille Syrjälä 		for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
1452b2432adfSVille Syrjälä 			if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
14536e22dc35SClaudio Suarez 				drm_dbg_atomic(dev, "[CRTC:%d:%s] requires full modeset\n",
1454fa3ab4c2SVille Syrjälä 					       crtc->base.id, crtc->name);
1455d34f20d6SRob Clark 				return -EINVAL;
1456d34f20d6SRob Clark 			}
1457d34f20d6SRob Clark 		}
1458d34f20d6SRob Clark 	}
1459d34f20d6SRob Clark 
14605ec1cebdSManasi Navare 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
14615ec1cebdSManasi Navare 		if (new_crtc_state->enable)
1462fb6473a4SDaniel Vetter 			affected_crtc |= drm_crtc_mask(crtc);
14635ec1cebdSManasi Navare 	}
1464fb6473a4SDaniel Vetter 
1465fb6473a4SDaniel Vetter 	/*
1466fb6473a4SDaniel Vetter 	 * For commits that allow modesets drivers can add other CRTCs to the
1467fb6473a4SDaniel Vetter 	 * atomic commit, e.g. when they need to reallocate global resources.
1468fb6473a4SDaniel Vetter 	 * This can cause spurious EBUSY, which robs compositors of a very
1469fb6473a4SDaniel Vetter 	 * effective sanity check for their drawing loop. Therefor only allow
1470fb6473a4SDaniel Vetter 	 * drivers to add unrelated CRTC states for modeset commits.
1471fb6473a4SDaniel Vetter 	 *
1472fb6473a4SDaniel Vetter 	 * FIXME: Should add affected_crtc mask to the ATOMIC IOCTL as an output
1473fb6473a4SDaniel Vetter 	 * so compositors know what's going on.
1474fb6473a4SDaniel Vetter 	 */
1475fb6473a4SDaniel Vetter 	if (affected_crtc != requested_crtc) {
14766e22dc35SClaudio Suarez 		drm_dbg_atomic(dev,
14776e22dc35SClaudio Suarez 			       "driver added CRTC to commit: requested 0x%x, affected 0x%0x\n",
1478fb6473a4SDaniel Vetter 			       requested_crtc, affected_crtc);
1479fb6473a4SDaniel Vetter 		WARN(!state->allow_modeset, "adding CRTC not allowed without modesets: requested 0x%x, affected 0x%0x\n",
1480fb6473a4SDaniel Vetter 		     requested_crtc, affected_crtc);
1481fb6473a4SDaniel Vetter 	}
1482fb6473a4SDaniel Vetter 
1483a0ffc51eSMaarten Lankhorst 	return 0;
1484cc4ceb48SDaniel Vetter }
1485cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_check_only);
1486cc4ceb48SDaniel Vetter 
1487cc4ceb48SDaniel Vetter /**
1488cc4ceb48SDaniel Vetter  * drm_atomic_commit - commit configuration atomically
1489cc4ceb48SDaniel Vetter  * @state: atomic configuration to check
1490cc4ceb48SDaniel Vetter  *
1491cc4ceb48SDaniel Vetter  * Note that this function can return -EDEADLK if the driver needed to acquire
1492cc4ceb48SDaniel Vetter  * more locks but encountered a deadlock. The caller must then do the usual w/w
1493cc4ceb48SDaniel Vetter  * backoff dance and restart. All other errors are fatal.
1494cc4ceb48SDaniel Vetter  *
149576fede2fSMaarten Lankhorst  * This function will take its own reference on @state.
149676fede2fSMaarten Lankhorst  * Callers should always release their reference with drm_atomic_state_put().
1497cc4ceb48SDaniel Vetter  *
1498cc4ceb48SDaniel Vetter  * Returns:
1499cc4ceb48SDaniel Vetter  * 0 on success, negative error code on failure.
1500cc4ceb48SDaniel Vetter  */
drm_atomic_commit(struct drm_atomic_state * state)1501cc4ceb48SDaniel Vetter int drm_atomic_commit(struct drm_atomic_state *state)
1502cc4ceb48SDaniel Vetter {
1503cc4ceb48SDaniel Vetter 	struct drm_mode_config *config = &state->dev->mode_config;
1504018ad18fSMaxime Ripard 	struct drm_printer p = drm_info_printer(state->dev->dev);
1505cc4ceb48SDaniel Vetter 	int ret;
1506cc4ceb48SDaniel Vetter 
1507018ad18fSMaxime Ripard 	if (drm_debug_enabled(DRM_UT_STATE))
1508018ad18fSMaxime Ripard 		drm_atomic_print_new_state(state, &p);
1509018ad18fSMaxime Ripard 
1510cc4ceb48SDaniel Vetter 	ret = drm_atomic_check_only(state);
1511cc4ceb48SDaniel Vetter 	if (ret)
1512cc4ceb48SDaniel Vetter 		return ret;
1513cc4ceb48SDaniel Vetter 
15146e22dc35SClaudio Suarez 	drm_dbg_atomic(state->dev, "committing %p\n", state);
1515cc4ceb48SDaniel Vetter 
1516cc4ceb48SDaniel Vetter 	return config->funcs->atomic_commit(state->dev, state, false);
1517cc4ceb48SDaniel Vetter }
1518cc4ceb48SDaniel Vetter EXPORT_SYMBOL(drm_atomic_commit);
1519cc4ceb48SDaniel Vetter 
1520cc4ceb48SDaniel Vetter /**
1521d574528aSDaniel Vetter  * drm_atomic_nonblocking_commit - atomic nonblocking commit
1522cc4ceb48SDaniel Vetter  * @state: atomic configuration to check
1523cc4ceb48SDaniel Vetter  *
1524cc4ceb48SDaniel Vetter  * Note that this function can return -EDEADLK if the driver needed to acquire
1525cc4ceb48SDaniel Vetter  * more locks but encountered a deadlock. The caller must then do the usual w/w
1526cc4ceb48SDaniel Vetter  * backoff dance and restart. All other errors are fatal.
1527cc4ceb48SDaniel Vetter  *
152876fede2fSMaarten Lankhorst  * This function will take its own reference on @state.
152976fede2fSMaarten Lankhorst  * Callers should always release their reference with drm_atomic_state_put().
1530cc4ceb48SDaniel Vetter  *
1531cc4ceb48SDaniel Vetter  * Returns:
1532cc4ceb48SDaniel Vetter  * 0 on success, negative error code on failure.
1533cc4ceb48SDaniel Vetter  */
drm_atomic_nonblocking_commit(struct drm_atomic_state * state)1534b837ba0aSMaarten Lankhorst int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
1535cc4ceb48SDaniel Vetter {
1536cc4ceb48SDaniel Vetter 	struct drm_mode_config *config = &state->dev->mode_config;
1537cc4ceb48SDaniel Vetter 	int ret;
1538cc4ceb48SDaniel Vetter 
1539cc4ceb48SDaniel Vetter 	ret = drm_atomic_check_only(state);
1540cc4ceb48SDaniel Vetter 	if (ret)
1541cc4ceb48SDaniel Vetter 		return ret;
1542cc4ceb48SDaniel Vetter 
15436e22dc35SClaudio Suarez 	drm_dbg_atomic(state->dev, "committing %p nonblocking\n", state);
1544cc4ceb48SDaniel Vetter 
1545cc4ceb48SDaniel Vetter 	return config->funcs->atomic_commit(state->dev, state, true);
1546cc4ceb48SDaniel Vetter }
1547b837ba0aSMaarten Lankhorst EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
1548d34f20d6SRob Clark 
1549df737895SNoralf Trønnes /* just used from drm-client and atomic-helper: */
__drm_atomic_helper_disable_plane(struct drm_plane * plane,struct drm_plane_state * plane_state)1550df737895SNoralf Trønnes int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
1551df737895SNoralf Trønnes 				      struct drm_plane_state *plane_state)
1552df737895SNoralf Trønnes {
1553df737895SNoralf Trønnes 	int ret;
1554df737895SNoralf Trønnes 
1555df737895SNoralf Trønnes 	ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
1556df737895SNoralf Trønnes 	if (ret != 0)
1557df737895SNoralf Trønnes 		return ret;
1558df737895SNoralf Trønnes 
1559df737895SNoralf Trønnes 	drm_atomic_set_fb_for_plane(plane_state, NULL);
1560df737895SNoralf Trønnes 	plane_state->crtc_x = 0;
1561df737895SNoralf Trønnes 	plane_state->crtc_y = 0;
1562df737895SNoralf Trønnes 	plane_state->crtc_w = 0;
1563df737895SNoralf Trønnes 	plane_state->crtc_h = 0;
1564df737895SNoralf Trønnes 	plane_state->src_x = 0;
1565df737895SNoralf Trønnes 	plane_state->src_y = 0;
1566df737895SNoralf Trønnes 	plane_state->src_w = 0;
1567df737895SNoralf Trønnes 	plane_state->src_h = 0;
1568df737895SNoralf Trønnes 
1569df737895SNoralf Trønnes 	return 0;
1570df737895SNoralf Trønnes }
1571df737895SNoralf Trønnes EXPORT_SYMBOL(__drm_atomic_helper_disable_plane);
1572df737895SNoralf Trønnes 
update_output_state(struct drm_atomic_state * state,struct drm_mode_set * set)1573df737895SNoralf Trønnes static int update_output_state(struct drm_atomic_state *state,
1574df737895SNoralf Trønnes 			       struct drm_mode_set *set)
1575df737895SNoralf Trønnes {
1576df737895SNoralf Trønnes 	struct drm_device *dev = set->crtc->dev;
1577df737895SNoralf Trønnes 	struct drm_crtc *crtc;
1578df737895SNoralf Trønnes 	struct drm_crtc_state *new_crtc_state;
1579df737895SNoralf Trønnes 	struct drm_connector *connector;
1580df737895SNoralf Trønnes 	struct drm_connector_state *new_conn_state;
1581df737895SNoralf Trønnes 	int ret, i;
1582df737895SNoralf Trønnes 
1583df737895SNoralf Trønnes 	ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
1584df737895SNoralf Trønnes 			       state->acquire_ctx);
1585df737895SNoralf Trønnes 	if (ret)
1586df737895SNoralf Trønnes 		return ret;
1587df737895SNoralf Trønnes 
1588df737895SNoralf Trønnes 	/* First disable all connectors on the target crtc. */
1589df737895SNoralf Trønnes 	ret = drm_atomic_add_affected_connectors(state, set->crtc);
1590df737895SNoralf Trønnes 	if (ret)
1591df737895SNoralf Trønnes 		return ret;
1592df737895SNoralf Trønnes 
1593df737895SNoralf Trønnes 	for_each_new_connector_in_state(state, connector, new_conn_state, i) {
1594df737895SNoralf Trønnes 		if (new_conn_state->crtc == set->crtc) {
1595df737895SNoralf Trønnes 			ret = drm_atomic_set_crtc_for_connector(new_conn_state,
1596df737895SNoralf Trønnes 								NULL);
1597df737895SNoralf Trønnes 			if (ret)
1598df737895SNoralf Trønnes 				return ret;
1599df737895SNoralf Trønnes 
1600df737895SNoralf Trønnes 			/* Make sure legacy setCrtc always re-trains */
1601df737895SNoralf Trønnes 			new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
1602df737895SNoralf Trønnes 		}
1603df737895SNoralf Trønnes 	}
1604df737895SNoralf Trønnes 
1605df737895SNoralf Trønnes 	/* Then set all connectors from set->connectors on the target crtc */
1606df737895SNoralf Trønnes 	for (i = 0; i < set->num_connectors; i++) {
1607df737895SNoralf Trønnes 		new_conn_state = drm_atomic_get_connector_state(state,
1608df737895SNoralf Trønnes 								set->connectors[i]);
1609df737895SNoralf Trønnes 		if (IS_ERR(new_conn_state))
1610df737895SNoralf Trønnes 			return PTR_ERR(new_conn_state);
1611df737895SNoralf Trønnes 
1612df737895SNoralf Trønnes 		ret = drm_atomic_set_crtc_for_connector(new_conn_state,
1613df737895SNoralf Trønnes 							set->crtc);
1614df737895SNoralf Trønnes 		if (ret)
1615df737895SNoralf Trønnes 			return ret;
1616df737895SNoralf Trønnes 	}
1617df737895SNoralf Trønnes 
1618df737895SNoralf Trønnes 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
1619df737895SNoralf Trønnes 		/*
1620df737895SNoralf Trønnes 		 * Don't update ->enable for the CRTC in the set_config request,
1621df737895SNoralf Trønnes 		 * since a mismatch would indicate a bug in the upper layers.
1622df737895SNoralf Trønnes 		 * The actual modeset code later on will catch any
1623df737895SNoralf Trønnes 		 * inconsistencies here.
1624df737895SNoralf Trønnes 		 */
1625df737895SNoralf Trønnes 		if (crtc == set->crtc)
1626df737895SNoralf Trønnes 			continue;
1627df737895SNoralf Trønnes 
1628df737895SNoralf Trønnes 		if (!new_crtc_state->connector_mask) {
1629df737895SNoralf Trønnes 			ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state,
1630df737895SNoralf Trønnes 								NULL);
1631df737895SNoralf Trønnes 			if (ret < 0)
1632df737895SNoralf Trønnes 				return ret;
1633df737895SNoralf Trønnes 
1634df737895SNoralf Trønnes 			new_crtc_state->active = false;
1635df737895SNoralf Trønnes 		}
1636df737895SNoralf Trønnes 	}
1637df737895SNoralf Trønnes 
1638df737895SNoralf Trønnes 	return 0;
1639df737895SNoralf Trønnes }
1640df737895SNoralf Trønnes 
1641df737895SNoralf Trønnes /* just used from drm-client and atomic-helper: */
__drm_atomic_helper_set_config(struct drm_mode_set * set,struct drm_atomic_state * state)1642df737895SNoralf Trønnes int __drm_atomic_helper_set_config(struct drm_mode_set *set,
1643df737895SNoralf Trønnes 				   struct drm_atomic_state *state)
1644df737895SNoralf Trønnes {
1645df737895SNoralf Trønnes 	struct drm_crtc_state *crtc_state;
1646df737895SNoralf Trønnes 	struct drm_plane_state *primary_state;
1647df737895SNoralf Trønnes 	struct drm_crtc *crtc = set->crtc;
1648df737895SNoralf Trønnes 	int hdisplay, vdisplay;
1649df737895SNoralf Trønnes 	int ret;
1650df737895SNoralf Trønnes 
1651df737895SNoralf Trønnes 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
1652df737895SNoralf Trønnes 	if (IS_ERR(crtc_state))
1653df737895SNoralf Trønnes 		return PTR_ERR(crtc_state);
1654df737895SNoralf Trønnes 
1655df737895SNoralf Trønnes 	primary_state = drm_atomic_get_plane_state(state, crtc->primary);
1656df737895SNoralf Trønnes 	if (IS_ERR(primary_state))
1657df737895SNoralf Trønnes 		return PTR_ERR(primary_state);
1658df737895SNoralf Trønnes 
1659df737895SNoralf Trønnes 	if (!set->mode) {
1660df737895SNoralf Trønnes 		WARN_ON(set->fb);
1661df737895SNoralf Trønnes 		WARN_ON(set->num_connectors);
1662df737895SNoralf Trønnes 
1663df737895SNoralf Trønnes 		ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
1664df737895SNoralf Trønnes 		if (ret != 0)
1665df737895SNoralf Trønnes 			return ret;
1666df737895SNoralf Trønnes 
1667df737895SNoralf Trønnes 		crtc_state->active = false;
1668df737895SNoralf Trønnes 
1669df737895SNoralf Trønnes 		ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1670df737895SNoralf Trønnes 		if (ret != 0)
1671df737895SNoralf Trønnes 			return ret;
1672df737895SNoralf Trønnes 
1673df737895SNoralf Trønnes 		drm_atomic_set_fb_for_plane(primary_state, NULL);
1674df737895SNoralf Trønnes 
1675df737895SNoralf Trønnes 		goto commit;
1676df737895SNoralf Trønnes 	}
1677df737895SNoralf Trønnes 
1678df737895SNoralf Trønnes 	WARN_ON(!set->fb);
1679df737895SNoralf Trønnes 	WARN_ON(!set->num_connectors);
1680df737895SNoralf Trønnes 
1681df737895SNoralf Trønnes 	ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
1682df737895SNoralf Trønnes 	if (ret != 0)
1683df737895SNoralf Trønnes 		return ret;
1684df737895SNoralf Trønnes 
1685df737895SNoralf Trønnes 	crtc_state->active = true;
1686df737895SNoralf Trønnes 
1687df737895SNoralf Trønnes 	ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
1688df737895SNoralf Trønnes 	if (ret != 0)
1689df737895SNoralf Trønnes 		return ret;
1690df737895SNoralf Trønnes 
1691df737895SNoralf Trønnes 	drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay);
1692df737895SNoralf Trønnes 
1693df737895SNoralf Trønnes 	drm_atomic_set_fb_for_plane(primary_state, set->fb);
1694df737895SNoralf Trønnes 	primary_state->crtc_x = 0;
1695df737895SNoralf Trønnes 	primary_state->crtc_y = 0;
1696df737895SNoralf Trønnes 	primary_state->crtc_w = hdisplay;
1697df737895SNoralf Trønnes 	primary_state->crtc_h = vdisplay;
1698df737895SNoralf Trønnes 	primary_state->src_x = set->x << 16;
1699df737895SNoralf Trønnes 	primary_state->src_y = set->y << 16;
1700df737895SNoralf Trønnes 	if (drm_rotation_90_or_270(primary_state->rotation)) {
1701df737895SNoralf Trønnes 		primary_state->src_w = vdisplay << 16;
1702df737895SNoralf Trønnes 		primary_state->src_h = hdisplay << 16;
1703df737895SNoralf Trønnes 	} else {
1704df737895SNoralf Trønnes 		primary_state->src_w = hdisplay << 16;
1705df737895SNoralf Trønnes 		primary_state->src_h = vdisplay << 16;
1706df737895SNoralf Trønnes 	}
1707df737895SNoralf Trønnes 
1708df737895SNoralf Trønnes commit:
1709df737895SNoralf Trønnes 	ret = update_output_state(state, set);
1710df737895SNoralf Trønnes 	if (ret)
1711df737895SNoralf Trønnes 		return ret;
1712df737895SNoralf Trønnes 
1713df737895SNoralf Trønnes 	return 0;
1714df737895SNoralf Trønnes }
1715df737895SNoralf Trønnes EXPORT_SYMBOL(__drm_atomic_helper_set_config);
1716df737895SNoralf Trønnes 
drm_atomic_private_obj_print_state(struct drm_printer * p,const struct drm_private_state * state)171797a1f01bSMaxime Ripard static void drm_atomic_private_obj_print_state(struct drm_printer *p,
171897a1f01bSMaxime Ripard 					       const struct drm_private_state *state)
171997a1f01bSMaxime Ripard {
172097a1f01bSMaxime Ripard 	struct drm_private_obj *obj = state->obj;
172197a1f01bSMaxime Ripard 
172297a1f01bSMaxime Ripard 	if (obj->funcs->atomic_print_state)
172397a1f01bSMaxime Ripard 		obj->funcs->atomic_print_state(p, state);
172497a1f01bSMaxime Ripard }
172597a1f01bSMaxime Ripard 
1726a4324a7aSAbhinav Kumar /**
1727a4324a7aSAbhinav Kumar  * drm_atomic_print_new_state - prints drm atomic state
1728a4324a7aSAbhinav Kumar  * @state: atomic configuration to check
1729a4324a7aSAbhinav Kumar  * @p: drm printer
1730a4324a7aSAbhinav Kumar  *
1731a4324a7aSAbhinav Kumar  * This functions prints the drm atomic state snapshot using the drm printer
1732a4324a7aSAbhinav Kumar  * which is passed to it. This snapshot can be used for debugging purposes.
1733a4324a7aSAbhinav Kumar  *
1734a4324a7aSAbhinav Kumar  * Note that this function looks into the new state objects and hence its not
1735a4324a7aSAbhinav Kumar  * safe to be used after the call to drm_atomic_helper_commit_hw_done().
1736a4324a7aSAbhinav Kumar  */
drm_atomic_print_new_state(const struct drm_atomic_state * state,struct drm_printer * p)1737a4324a7aSAbhinav Kumar void drm_atomic_print_new_state(const struct drm_atomic_state *state,
1738a4324a7aSAbhinav Kumar 		struct drm_printer *p)
1739fceffb32SRob Clark {
1740fceffb32SRob Clark 	struct drm_plane *plane;
1741fceffb32SRob Clark 	struct drm_plane_state *plane_state;
1742fceffb32SRob Clark 	struct drm_crtc *crtc;
1743fceffb32SRob Clark 	struct drm_crtc_state *crtc_state;
1744fceffb32SRob Clark 	struct drm_connector *connector;
1745fceffb32SRob Clark 	struct drm_connector_state *connector_state;
174697a1f01bSMaxime Ripard 	struct drm_private_obj *obj;
174797a1f01bSMaxime Ripard 	struct drm_private_state *obj_state;
1748fceffb32SRob Clark 	int i;
1749fceffb32SRob Clark 
1750a4324a7aSAbhinav Kumar 	if (!p) {
17516e22dc35SClaudio Suarez 		drm_err(state->dev, "invalid drm printer\n");
1752a4324a7aSAbhinav Kumar 		return;
1753a4324a7aSAbhinav Kumar 	}
1754a4324a7aSAbhinav Kumar 
17556e22dc35SClaudio Suarez 	drm_dbg_atomic(state->dev, "checking %p\n", state);
1756fceffb32SRob Clark 
17575721a380SMaarten Lankhorst 	for_each_new_plane_in_state(state, plane, plane_state, i)
1758a4324a7aSAbhinav Kumar 		drm_atomic_plane_print_state(p, plane_state);
1759fceffb32SRob Clark 
17605721a380SMaarten Lankhorst 	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
1761a4324a7aSAbhinav Kumar 		drm_atomic_crtc_print_state(p, crtc_state);
1762fceffb32SRob Clark 
17635721a380SMaarten Lankhorst 	for_each_new_connector_in_state(state, connector, connector_state, i)
1764a4324a7aSAbhinav Kumar 		drm_atomic_connector_print_state(p, connector_state);
176597a1f01bSMaxime Ripard 
176697a1f01bSMaxime Ripard 	for_each_new_private_obj_in_state(state, obj, obj_state, i)
176797a1f01bSMaxime Ripard 		drm_atomic_private_obj_print_state(p, obj_state);
1768fceffb32SRob Clark }
1769a4324a7aSAbhinav Kumar EXPORT_SYMBOL(drm_atomic_print_new_state);
1770fceffb32SRob Clark 
__drm_state_dump(struct drm_device * dev,struct drm_printer * p,bool take_locks)1771c2d85564SDaniel Vetter static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
1772c2d85564SDaniel Vetter 			     bool take_locks)
1773c2d85564SDaniel Vetter {
1774c2d85564SDaniel Vetter 	struct drm_mode_config *config = &dev->mode_config;
1775c2d85564SDaniel Vetter 	struct drm_plane *plane;
1776c2d85564SDaniel Vetter 	struct drm_crtc *crtc;
1777c2d85564SDaniel Vetter 	struct drm_connector *connector;
1778c2d85564SDaniel Vetter 	struct drm_connector_list_iter conn_iter;
1779c8fa1cc0SDmitry Baryshkov 	struct drm_private_obj *obj;
1780c2d85564SDaniel Vetter 
17813c499ea0SLyude Paul 	if (!drm_drv_uses_atomic_modeset(dev))
1782c2d85564SDaniel Vetter 		return;
1783c2d85564SDaniel Vetter 
1784c2d85564SDaniel Vetter 	list_for_each_entry(plane, &config->plane_list, head) {
1785c2d85564SDaniel Vetter 		if (take_locks)
1786c2d85564SDaniel Vetter 			drm_modeset_lock(&plane->mutex, NULL);
1787c2d85564SDaniel Vetter 		drm_atomic_plane_print_state(p, plane->state);
1788c2d85564SDaniel Vetter 		if (take_locks)
1789c2d85564SDaniel Vetter 			drm_modeset_unlock(&plane->mutex);
1790c2d85564SDaniel Vetter 	}
1791c2d85564SDaniel Vetter 
1792c2d85564SDaniel Vetter 	list_for_each_entry(crtc, &config->crtc_list, head) {
1793c2d85564SDaniel Vetter 		if (take_locks)
1794c2d85564SDaniel Vetter 			drm_modeset_lock(&crtc->mutex, NULL);
1795c2d85564SDaniel Vetter 		drm_atomic_crtc_print_state(p, crtc->state);
1796c2d85564SDaniel Vetter 		if (take_locks)
1797c2d85564SDaniel Vetter 			drm_modeset_unlock(&crtc->mutex);
1798c2d85564SDaniel Vetter 	}
1799c2d85564SDaniel Vetter 
1800c2d85564SDaniel Vetter 	drm_connector_list_iter_begin(dev, &conn_iter);
1801c2d85564SDaniel Vetter 	if (take_locks)
1802c2d85564SDaniel Vetter 		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1803c2d85564SDaniel Vetter 	drm_for_each_connector_iter(connector, &conn_iter)
1804c2d85564SDaniel Vetter 		drm_atomic_connector_print_state(p, connector->state);
1805c2d85564SDaniel Vetter 	if (take_locks)
1806c2d85564SDaniel Vetter 		drm_modeset_unlock(&dev->mode_config.connection_mutex);
1807c2d85564SDaniel Vetter 	drm_connector_list_iter_end(&conn_iter);
1808c8fa1cc0SDmitry Baryshkov 
1809c8fa1cc0SDmitry Baryshkov 	list_for_each_entry(obj, &config->privobj_list, head) {
1810c8fa1cc0SDmitry Baryshkov 		if (take_locks)
1811c8fa1cc0SDmitry Baryshkov 			drm_modeset_lock(&obj->lock, NULL);
1812c8fa1cc0SDmitry Baryshkov 		drm_atomic_private_obj_print_state(p, obj->state);
1813c8fa1cc0SDmitry Baryshkov 		if (take_locks)
1814c8fa1cc0SDmitry Baryshkov 			drm_modeset_unlock(&obj->lock);
1815c8fa1cc0SDmitry Baryshkov 	}
1816c2d85564SDaniel Vetter }
1817c2d85564SDaniel Vetter 
18186559c901SRob Clark /**
18196559c901SRob Clark  * drm_state_dump - dump entire device atomic state
18206559c901SRob Clark  * @dev: the drm device
18216559c901SRob Clark  * @p: where to print the state to
18226559c901SRob Clark  *
18236559c901SRob Clark  * Just for debugging.  Drivers might want an option to dump state
18246559c901SRob Clark  * to dmesg in case of error irq's.  (Hint, you probably want to
18256559c901SRob Clark  * ratelimit this!)
18266559c901SRob Clark  *
1827bd1fbef7SDaniel Vetter  * The caller must wrap this drm_modeset_lock_all_ctx() and
1828bd1fbef7SDaniel Vetter  * drm_modeset_drop_locks(). If this is called from error irq handler, it should
1829bd1fbef7SDaniel Vetter  * not be enabled by default - if you are debugging errors you might
1830bd1fbef7SDaniel Vetter  * not care that this is racey, but calling this without all modeset locks held
1831bd1fbef7SDaniel Vetter  * is inherently unsafe.
18326559c901SRob Clark  */
drm_state_dump(struct drm_device * dev,struct drm_printer * p)18336559c901SRob Clark void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
18346559c901SRob Clark {
1835c2d85564SDaniel Vetter 	__drm_state_dump(dev, p, false);
18366559c901SRob Clark }
18376559c901SRob Clark EXPORT_SYMBOL(drm_state_dump);
18386559c901SRob Clark 
18396559c901SRob Clark #ifdef CONFIG_DEBUG_FS
drm_state_info(struct seq_file * m,void * data)18406559c901SRob Clark static int drm_state_info(struct seq_file *m, void *data)
18416559c901SRob Clark {
18426fd80729SMaíra Canal 	struct drm_debugfs_entry *entry = m->private;
18436fd80729SMaíra Canal 	struct drm_device *dev = entry->dev;
18446559c901SRob Clark 	struct drm_printer p = drm_seq_file_printer(m);
18456559c901SRob Clark 
1846c2d85564SDaniel Vetter 	__drm_state_dump(dev, &p, true);
18476559c901SRob Clark 
18486559c901SRob Clark 	return 0;
18496559c901SRob Clark }
18506559c901SRob Clark 
18516559c901SRob Clark /* any use in debugfs files to dump individual planes/crtc/etc? */
18526fd80729SMaíra Canal static const struct drm_debugfs_info drm_atomic_debugfs_list[] = {
18536559c901SRob Clark 	{"state", drm_state_info, 0},
18546559c901SRob Clark };
18556559c901SRob Clark 
drm_atomic_debugfs_init(struct drm_device * dev)18560b30d57aSChristian König void drm_atomic_debugfs_init(struct drm_device *dev)
18576559c901SRob Clark {
18580b30d57aSChristian König 	drm_debugfs_add_files(dev, drm_atomic_debugfs_list,
18596fd80729SMaíra Canal 			      ARRAY_SIZE(drm_atomic_debugfs_list));
18606559c901SRob Clark }
18616559c901SRob Clark #endif
1862