1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58#include "display/intel_dp.h"
59
60#include "i915_drv.h"
61#include "intel_display_types.h"
62#include "intel_fbc.h"
63#include "intel_frontbuffer.h"
64#include "intel_psr.h"
65
66
67
68
69
70
71
72
73
74
75
76
77
78static void frontbuffer_flush(struct drm_i915_private *i915,
79 unsigned int frontbuffer_bits,
80 enum fb_op_origin origin)
81{
82
83 spin_lock(&i915->fb_tracking.lock);
84 frontbuffer_bits &= ~i915->fb_tracking.busy_bits;
85 spin_unlock(&i915->fb_tracking.lock);
86
87 if (!frontbuffer_bits)
88 return;
89
90 might_sleep();
91 intel_edp_drrs_flush(i915, frontbuffer_bits);
92 intel_psr_flush(i915, frontbuffer_bits, origin);
93 intel_fbc_flush(i915, frontbuffer_bits, origin);
94}
95
96
97
98
99
100
101
102
103
104
105
106
107
108void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
109 unsigned frontbuffer_bits)
110{
111 spin_lock(&i915->fb_tracking.lock);
112 i915->fb_tracking.flip_bits |= frontbuffer_bits;
113
114 i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
115 spin_unlock(&i915->fb_tracking.lock);
116}
117
118
119
120
121
122
123
124
125
126
127
128void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
129 unsigned frontbuffer_bits)
130{
131 spin_lock(&i915->fb_tracking.lock);
132
133 frontbuffer_bits &= i915->fb_tracking.flip_bits;
134 i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
135 spin_unlock(&i915->fb_tracking.lock);
136
137 if (frontbuffer_bits)
138 frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
139}
140
141
142
143
144
145
146
147
148
149
150
151
152void intel_frontbuffer_flip(struct drm_i915_private *i915,
153 unsigned frontbuffer_bits)
154{
155 spin_lock(&i915->fb_tracking.lock);
156
157 i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
158 spin_unlock(&i915->fb_tracking.lock);
159
160 frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
161}
162
163void __intel_fb_invalidate(struct intel_frontbuffer *front,
164 enum fb_op_origin origin,
165 unsigned int frontbuffer_bits)
166{
167 struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
168
169 if (origin == ORIGIN_CS) {
170 spin_lock(&i915->fb_tracking.lock);
171 i915->fb_tracking.busy_bits |= frontbuffer_bits;
172 i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
173 spin_unlock(&i915->fb_tracking.lock);
174 }
175
176 might_sleep();
177 intel_psr_invalidate(i915, frontbuffer_bits, origin);
178 intel_edp_drrs_invalidate(i915, frontbuffer_bits);
179 intel_fbc_invalidate(i915, frontbuffer_bits, origin);
180}
181
182void __intel_fb_flush(struct intel_frontbuffer *front,
183 enum fb_op_origin origin,
184 unsigned int frontbuffer_bits)
185{
186 struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
187
188 if (origin == ORIGIN_CS) {
189 spin_lock(&i915->fb_tracking.lock);
190
191 frontbuffer_bits &= i915->fb_tracking.busy_bits;
192 i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
193 spin_unlock(&i915->fb_tracking.lock);
194 }
195
196 if (frontbuffer_bits)
197 frontbuffer_flush(i915, frontbuffer_bits, origin);
198}
199
200static int frontbuffer_active(struct i915_active *ref)
201{
202 struct intel_frontbuffer *front =
203 container_of(ref, typeof(*front), write);
204
205 kref_get(&front->ref);
206 return 0;
207}
208
209__i915_active_call
210static void frontbuffer_retire(struct i915_active *ref)
211{
212 struct intel_frontbuffer *front =
213 container_of(ref, typeof(*front), write);
214
215 intel_frontbuffer_flush(front, ORIGIN_CS);
216 intel_frontbuffer_put(front);
217}
218
219static void frontbuffer_release(struct kref *ref)
220 __releases(&to_i915(front->obj->base.dev)->fb_tracking.lock)
221{
222 struct intel_frontbuffer *front =
223 container_of(ref, typeof(*front), ref);
224 struct drm_i915_gem_object *obj = front->obj;
225 struct i915_vma *vma;
226
227 spin_lock(&obj->vma.lock);
228 for_each_ggtt_vma(vma, obj) {
229 i915_vma_clear_scanout(vma);
230 vma->display_alignment = I915_GTT_MIN_ALIGNMENT;
231 }
232 spin_unlock(&obj->vma.lock);
233
234 RCU_INIT_POINTER(obj->frontbuffer, NULL);
235 spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock);
236
237 i915_active_fini(&front->write);
238
239 i915_gem_object_put(obj);
240 kfree_rcu(front, rcu);
241}
242
243struct intel_frontbuffer *
244intel_frontbuffer_get(struct drm_i915_gem_object *obj)
245{
246 struct drm_i915_private *i915 = to_i915(obj->base.dev);
247 struct intel_frontbuffer *front;
248
249 front = __intel_frontbuffer_get(obj);
250 if (front)
251 return front;
252
253 front = kmalloc(sizeof(*front), GFP_KERNEL);
254 if (!front)
255 return NULL;
256
257 front->obj = obj;
258 kref_init(&front->ref);
259 atomic_set(&front->bits, 0);
260 i915_active_init(&front->write,
261 frontbuffer_active,
262 i915_active_may_sleep(frontbuffer_retire));
263
264 spin_lock(&i915->fb_tracking.lock);
265 if (rcu_access_pointer(obj->frontbuffer)) {
266 kfree(front);
267 front = rcu_dereference_protected(obj->frontbuffer, true);
268 kref_get(&front->ref);
269 } else {
270 i915_gem_object_get(obj);
271 rcu_assign_pointer(obj->frontbuffer, front);
272 }
273 spin_unlock(&i915->fb_tracking.lock);
274
275 return front;
276}
277
278void intel_frontbuffer_put(struct intel_frontbuffer *front)
279{
280 kref_put_lock(&front->ref,
281 frontbuffer_release,
282 &to_i915(front->obj->base.dev)->fb_tracking.lock);
283}
284
285
286
287
288
289
290
291
292
293
294void intel_frontbuffer_track(struct intel_frontbuffer *old,
295 struct intel_frontbuffer *new,
296 unsigned int frontbuffer_bits)
297{
298
299
300
301
302
303
304
305 BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES >
306 BITS_PER_TYPE(atomic_t));
307
308 if (old) {
309 drm_WARN_ON(old->obj->base.dev,
310 !(atomic_read(&old->bits) & frontbuffer_bits));
311 atomic_andnot(frontbuffer_bits, &old->bits);
312 }
313
314 if (new) {
315 drm_WARN_ON(new->obj->base.dev,
316 atomic_read(&new->bits) & frontbuffer_bits);
317 atomic_or(frontbuffer_bits, &new->bits);
318 }
319}
320