1 // SPDX-License-Identifier: MIT
3 * Copyright © 2020 Intel Corporation
6 #include <linux/string.h>
9 #include "intel_atomic.h"
10 #include "intel_display_types.h"
11 #include "intel_global_state.h"
13 static void __intel_atomic_global_state_free(struct kref
*kref
)
15 struct intel_global_state
*obj_state
=
16 container_of(kref
, struct intel_global_state
, ref
);
17 struct intel_global_obj
*obj
= obj_state
->obj
;
19 obj
->funcs
->atomic_destroy_state(obj
, obj_state
);
22 static void intel_atomic_global_state_put(struct intel_global_state
*obj_state
)
24 kref_put(&obj_state
->ref
, __intel_atomic_global_state_free
);
27 static struct intel_global_state
*
28 intel_atomic_global_state_get(struct intel_global_state
*obj_state
)
30 kref_get(&obj_state
->ref
);
35 void intel_atomic_global_obj_init(struct drm_i915_private
*dev_priv
,
36 struct intel_global_obj
*obj
,
37 struct intel_global_state
*state
,
38 const struct intel_global_state_funcs
*funcs
)
40 memset(obj
, 0, sizeof(*obj
));
44 kref_init(&state
->ref
);
48 list_add_tail(&obj
->head
, &dev_priv
->global_obj_list
);
51 void intel_atomic_global_obj_cleanup(struct drm_i915_private
*dev_priv
)
53 struct intel_global_obj
*obj
, *next
;
55 list_for_each_entry_safe(obj
, next
, &dev_priv
->global_obj_list
, head
) {
58 drm_WARN_ON(&dev_priv
->drm
, kref_read(&obj
->state
->ref
) != 1);
59 intel_atomic_global_state_put(obj
->state
);
63 static void assert_global_state_write_locked(struct drm_i915_private
*dev_priv
)
65 struct intel_crtc
*crtc
;
67 for_each_intel_crtc(&dev_priv
->drm
, crtc
)
68 drm_modeset_lock_assert_held(&crtc
->base
.mutex
);
71 static bool modeset_lock_is_held(struct drm_modeset_acquire_ctx
*ctx
,
72 struct drm_modeset_lock
*lock
)
74 struct drm_modeset_lock
*l
;
76 list_for_each_entry(l
, &ctx
->locked
, head
) {
84 static void assert_global_state_read_locked(struct intel_atomic_state
*state
)
86 struct drm_modeset_acquire_ctx
*ctx
= state
->base
.acquire_ctx
;
87 struct drm_i915_private
*dev_priv
= to_i915(state
->base
.dev
);
88 struct intel_crtc
*crtc
;
90 for_each_intel_crtc(&dev_priv
->drm
, crtc
) {
91 if (modeset_lock_is_held(ctx
, &crtc
->base
.mutex
))
95 drm_WARN(&dev_priv
->drm
, 1, "Global state not read locked\n");
98 struct intel_global_state
*
99 intel_atomic_get_global_obj_state(struct intel_atomic_state
*state
,
100 struct intel_global_obj
*obj
)
102 struct drm_i915_private
*i915
= to_i915(state
->base
.dev
);
103 int index
, num_objs
, i
;
105 struct __intel_global_objs_state
*arr
;
106 struct intel_global_state
*obj_state
;
108 for (i
= 0; i
< state
->num_global_objs
; i
++)
109 if (obj
== state
->global_objs
[i
].ptr
)
110 return state
->global_objs
[i
].state
;
112 assert_global_state_read_locked(state
);
114 num_objs
= state
->num_global_objs
+ 1;
115 size
= sizeof(*state
->global_objs
) * num_objs
;
116 arr
= krealloc(state
->global_objs
, size
, GFP_KERNEL
);
118 return ERR_PTR(-ENOMEM
);
120 state
->global_objs
= arr
;
121 index
= state
->num_global_objs
;
122 memset(&state
->global_objs
[index
], 0, sizeof(*state
->global_objs
));
124 obj_state
= obj
->funcs
->atomic_duplicate_state(obj
);
126 return ERR_PTR(-ENOMEM
);
128 obj_state
->obj
= obj
;
129 obj_state
->changed
= false;
131 kref_init(&obj_state
->ref
);
133 state
->global_objs
[index
].state
= obj_state
;
134 state
->global_objs
[index
].old_state
=
135 intel_atomic_global_state_get(obj
->state
);
136 state
->global_objs
[index
].new_state
= obj_state
;
137 state
->global_objs
[index
].ptr
= obj
;
138 obj_state
->state
= state
;
140 state
->num_global_objs
= num_objs
;
142 drm_dbg_atomic(&i915
->drm
, "Added new global object %p state %p to %p\n",
143 obj
, obj_state
, state
);
148 struct intel_global_state
*
149 intel_atomic_get_old_global_obj_state(struct intel_atomic_state
*state
,
150 struct intel_global_obj
*obj
)
154 for (i
= 0; i
< state
->num_global_objs
; i
++)
155 if (obj
== state
->global_objs
[i
].ptr
)
156 return state
->global_objs
[i
].old_state
;
161 struct intel_global_state
*
162 intel_atomic_get_new_global_obj_state(struct intel_atomic_state
*state
,
163 struct intel_global_obj
*obj
)
167 for (i
= 0; i
< state
->num_global_objs
; i
++)
168 if (obj
== state
->global_objs
[i
].ptr
)
169 return state
->global_objs
[i
].new_state
;
174 void intel_atomic_swap_global_state(struct intel_atomic_state
*state
)
176 struct drm_i915_private
*dev_priv
= to_i915(state
->base
.dev
);
177 struct intel_global_state
*old_obj_state
, *new_obj_state
;
178 struct intel_global_obj
*obj
;
181 for_each_oldnew_global_obj_in_state(state
, obj
, old_obj_state
,
183 drm_WARN_ON(&dev_priv
->drm
, obj
->state
!= old_obj_state
);
186 * If the new state wasn't modified (and properly
187 * locked for write access) we throw it away.
189 if (!new_obj_state
->changed
)
192 assert_global_state_write_locked(dev_priv
);
194 old_obj_state
->state
= state
;
195 new_obj_state
->state
= NULL
;
197 state
->global_objs
[i
].state
= old_obj_state
;
199 intel_atomic_global_state_put(obj
->state
);
200 obj
->state
= intel_atomic_global_state_get(new_obj_state
);
204 void intel_atomic_clear_global_state(struct intel_atomic_state
*state
)
208 for (i
= 0; i
< state
->num_global_objs
; i
++) {
209 intel_atomic_global_state_put(state
->global_objs
[i
].old_state
);
210 intel_atomic_global_state_put(state
->global_objs
[i
].new_state
);
212 state
->global_objs
[i
].ptr
= NULL
;
213 state
->global_objs
[i
].state
= NULL
;
214 state
->global_objs
[i
].old_state
= NULL
;
215 state
->global_objs
[i
].new_state
= NULL
;
217 state
->num_global_objs
= 0;
220 int intel_atomic_lock_global_state(struct intel_global_state
*obj_state
)
222 struct intel_atomic_state
*state
= obj_state
->state
;
223 struct drm_i915_private
*dev_priv
= to_i915(state
->base
.dev
);
224 struct intel_crtc
*crtc
;
226 for_each_intel_crtc(&dev_priv
->drm
, crtc
) {
229 ret
= drm_modeset_lock(&crtc
->base
.mutex
,
230 state
->base
.acquire_ctx
);
235 obj_state
->changed
= true;
240 int intel_atomic_serialize_global_state(struct intel_global_state
*obj_state
)
242 struct intel_atomic_state
*state
= obj_state
->state
;
243 struct drm_i915_private
*dev_priv
= to_i915(state
->base
.dev
);
244 struct intel_crtc
*crtc
;
246 for_each_intel_crtc(&dev_priv
->drm
, crtc
) {
247 struct intel_crtc_state
*crtc_state
;
249 crtc_state
= intel_atomic_get_crtc_state(&state
->base
, crtc
);
250 if (IS_ERR(crtc_state
))
251 return PTR_ERR(crtc_state
);
254 obj_state
->changed
= true;