1 | /* |
2 | * Copyright © 2014 Intel Corporation |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice (including the next |
12 | * paragraph) shall be included in all copies or substantial portions of the |
13 | * Software. |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
21 | * DEALINGS IN THE SOFTWARE. |
22 | */ |
23 | |
24 | /** |
25 | * DOC: Frame Buffer Compression (FBC) |
26 | * |
27 | * FBC tries to save memory bandwidth (and so power consumption) by |
28 | * compressing the amount of memory used by the display. It is total |
29 | * transparent to user space and completely handled in the kernel. |
30 | * |
31 | * The benefits of FBC are mostly visible with solid backgrounds and |
32 | * variation-less patterns. It comes from keeping the memory footprint small |
33 | * and having fewer memory pages opened and accessed for refreshing the display. |
34 | * |
35 | * i915 is responsible to reserve stolen memory for FBC and configure its |
36 | * offset on proper registers. The hardware takes care of all |
37 | * compress/decompress. However there are many known cases where we have to |
38 | * forcibly disable it to allow proper screen updates. |
39 | */ |
40 | |
41 | #include <linux/string_helpers.h> |
42 | |
43 | #include <drm/drm_blend.h> |
44 | #include <drm/drm_fourcc.h> |
45 | |
46 | #include "i915_drv.h" |
47 | #include "i915_reg.h" |
48 | #include "i915_utils.h" |
49 | #include "i915_vgpu.h" |
50 | #include "i915_vma.h" |
51 | #include "intel_cdclk.h" |
52 | #include "intel_de.h" |
53 | #include "intel_display_device.h" |
54 | #include "intel_display_trace.h" |
55 | #include "intel_display_types.h" |
56 | #include "intel_fbc.h" |
57 | #include "intel_frontbuffer.h" |
58 | |
59 | #define for_each_fbc_id(__dev_priv, __fbc_id) \ |
60 | for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ |
61 | for_each_if(DISPLAY_RUNTIME_INFO(__dev_priv)->fbc_mask & BIT(__fbc_id)) |
62 | |
63 | #define for_each_intel_fbc(__dev_priv, __fbc, __fbc_id) \ |
64 | for_each_fbc_id((__dev_priv), (__fbc_id)) \ |
65 | for_each_if((__fbc) = (__dev_priv)->display.fbc[(__fbc_id)]) |
66 | |
67 | struct intel_fbc_funcs { |
68 | void (*activate)(struct intel_fbc *fbc); |
69 | void (*deactivate)(struct intel_fbc *fbc); |
70 | bool (*is_active)(struct intel_fbc *fbc); |
71 | bool (*is_compressing)(struct intel_fbc *fbc); |
72 | void (*nuke)(struct intel_fbc *fbc); |
73 | void (*program_cfb)(struct intel_fbc *fbc); |
74 | void (*set_false_color)(struct intel_fbc *fbc, bool enable); |
75 | }; |
76 | |
77 | struct intel_fbc_state { |
78 | struct intel_plane *plane; |
79 | unsigned int cfb_stride; |
80 | unsigned int cfb_size; |
81 | unsigned int fence_y_offset; |
82 | u16 override_cfb_stride; |
83 | u16 interval; |
84 | s8 fence_id; |
85 | }; |
86 | |
87 | struct intel_fbc { |
88 | struct drm_i915_private *i915; |
89 | const struct intel_fbc_funcs *funcs; |
90 | |
91 | /* |
92 | * This is always the inner lock when overlapping with |
93 | * struct_mutex and it's the outer lock when overlapping |
94 | * with stolen_lock. |
95 | */ |
96 | struct mutex lock; |
97 | unsigned int busy_bits; |
98 | |
99 | struct i915_stolen_fb compressed_fb, compressed_llb; |
100 | |
101 | enum intel_fbc_id id; |
102 | |
103 | u8 limit; |
104 | |
105 | bool false_color; |
106 | |
107 | bool active; |
108 | bool activated; |
109 | bool flip_pending; |
110 | |
111 | bool underrun_detected; |
112 | struct work_struct underrun_work; |
113 | |
114 | /* |
115 | * This structure contains everything that's relevant to program the |
116 | * hardware registers. When we want to figure out if we need to disable |
117 | * and re-enable FBC for a new configuration we just check if there's |
118 | * something different in the struct. The genx_fbc_activate functions |
119 | * are supposed to read from it in order to program the registers. |
120 | */ |
121 | struct intel_fbc_state state; |
122 | const char *no_fbc_reason; |
123 | }; |
124 | |
125 | /* plane stride in pixels */ |
126 | static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state) |
127 | { |
128 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
129 | unsigned int stride; |
130 | |
131 | stride = plane_state->view.color_plane[0].mapping_stride; |
132 | if (!drm_rotation_90_or_270(rotation: plane_state->hw.rotation)) |
133 | stride /= fb->format->cpp[0]; |
134 | |
135 | return stride; |
136 | } |
137 | |
138 | /* plane stride based cfb stride in bytes, assuming 1:1 compression limit */ |
139 | static unsigned int _intel_fbc_cfb_stride(const struct intel_plane_state *plane_state) |
140 | { |
141 | unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ |
142 | |
143 | return intel_fbc_plane_stride(plane_state) * cpp; |
144 | } |
145 | |
146 | /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */ |
147 | static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state *plane_state) |
148 | { |
149 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
150 | unsigned int limit = 4; /* 1:4 compression limit is the worst case */ |
151 | unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ |
152 | unsigned int width = drm_rect_width(r: &plane_state->uapi.src) >> 16; |
153 | unsigned int height = 4; /* FBC segment is 4 lines */ |
154 | unsigned int stride; |
155 | |
156 | /* minimum segment stride we can use */ |
157 | stride = width * cpp * height / limit; |
158 | |
159 | /* |
160 | * Wa_16011863758: icl+ |
161 | * Avoid some hardware segment address miscalculation. |
162 | */ |
163 | if (DISPLAY_VER(i915) >= 11) |
164 | stride += 64; |
165 | |
166 | /* |
167 | * At least some of the platforms require each 4 line segment to |
168 | * be 512 byte aligned. Just do it always for simplicity. |
169 | */ |
170 | stride = ALIGN(stride, 512); |
171 | |
172 | /* convert back to single line equivalent with 1:1 compression limit */ |
173 | return stride * limit / height; |
174 | } |
175 | |
176 | /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */ |
177 | static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_state) |
178 | { |
179 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
180 | unsigned int stride = _intel_fbc_cfb_stride(plane_state); |
181 | |
182 | /* |
183 | * At least some of the platforms require each 4 line segment to |
184 | * be 512 byte aligned. Aligning each line to 512 bytes guarantees |
185 | * that regardless of the compression limit we choose later. |
186 | */ |
187 | if (DISPLAY_VER(i915) >= 9) |
188 | return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(plane_state)); |
189 | else |
190 | return stride; |
191 | } |
192 | |
193 | static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state) |
194 | { |
195 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
196 | int lines = drm_rect_height(r: &plane_state->uapi.src) >> 16; |
197 | |
198 | if (DISPLAY_VER(i915) == 7) |
199 | lines = min(lines, 2048); |
200 | else if (DISPLAY_VER(i915) >= 8) |
201 | lines = min(lines, 2560); |
202 | |
203 | return lines * intel_fbc_cfb_stride(plane_state); |
204 | } |
205 | |
206 | static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_state) |
207 | { |
208 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
209 | unsigned int stride_aligned = intel_fbc_cfb_stride(plane_state); |
210 | unsigned int stride = _intel_fbc_cfb_stride(plane_state); |
211 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
212 | |
213 | /* |
214 | * Override stride in 64 byte units per 4 line segment. |
215 | * |
216 | * Gen9 hw miscalculates cfb stride for linear as |
217 | * PLANE_STRIDE*512 instead of PLANE_STRIDE*64, so |
218 | * we always need to use the override there. |
219 | */ |
220 | if (stride != stride_aligned || |
221 | (DISPLAY_VER(i915) == 9 && fb->modifier == DRM_FORMAT_MOD_LINEAR)) |
222 | return stride_aligned * 4 / 64; |
223 | |
224 | return 0; |
225 | } |
226 | |
227 | static u32 i8xx_fbc_ctl(struct intel_fbc *fbc) |
228 | { |
229 | const struct intel_fbc_state *fbc_state = &fbc->state; |
230 | struct drm_i915_private *i915 = fbc->i915; |
231 | unsigned int cfb_stride; |
232 | u32 fbc_ctl; |
233 | |
234 | cfb_stride = fbc_state->cfb_stride / fbc->limit; |
235 | |
236 | /* FBC_CTL wants 32B or 64B units */ |
237 | if (DISPLAY_VER(i915) == 2) |
238 | cfb_stride = (cfb_stride / 32) - 1; |
239 | else |
240 | cfb_stride = (cfb_stride / 64) - 1; |
241 | |
242 | fbc_ctl = FBC_CTL_PERIODIC | |
243 | FBC_CTL_INTERVAL(fbc_state->interval) | |
244 | FBC_CTL_STRIDE(cfb_stride); |
245 | |
246 | if (IS_I945GM(i915)) |
247 | fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ |
248 | |
249 | if (fbc_state->fence_id >= 0) |
250 | fbc_ctl |= FBC_CTL_FENCENO(fbc_state->fence_id); |
251 | |
252 | return fbc_ctl; |
253 | } |
254 | |
255 | static u32 i965_fbc_ctl2(struct intel_fbc *fbc) |
256 | { |
257 | const struct intel_fbc_state *fbc_state = &fbc->state; |
258 | u32 fbc_ctl2; |
259 | |
260 | fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | |
261 | FBC_CTL_PLANE(fbc_state->plane->i9xx_plane); |
262 | |
263 | if (fbc_state->fence_id >= 0) |
264 | fbc_ctl2 |= FBC_CTL_CPU_FENCE_EN; |
265 | |
266 | return fbc_ctl2; |
267 | } |
268 | |
269 | static void i8xx_fbc_deactivate(struct intel_fbc *fbc) |
270 | { |
271 | struct drm_i915_private *i915 = fbc->i915; |
272 | u32 fbc_ctl; |
273 | |
274 | /* Disable compression */ |
275 | fbc_ctl = intel_de_read(i915, FBC_CONTROL); |
276 | if ((fbc_ctl & FBC_CTL_EN) == 0) |
277 | return; |
278 | |
279 | fbc_ctl &= ~FBC_CTL_EN; |
280 | intel_de_write(i915, FBC_CONTROL, val: fbc_ctl); |
281 | |
282 | /* Wait for compressing bit to clear */ |
283 | if (intel_de_wait_for_clear(i915, FBC_STATUS, |
284 | FBC_STAT_COMPRESSING, timeout: 10)) { |
285 | drm_dbg_kms(&i915->drm, "FBC idle timed out\n" ); |
286 | return; |
287 | } |
288 | } |
289 | |
290 | static void i8xx_fbc_activate(struct intel_fbc *fbc) |
291 | { |
292 | const struct intel_fbc_state *fbc_state = &fbc->state; |
293 | struct drm_i915_private *i915 = fbc->i915; |
294 | int i; |
295 | |
296 | /* Clear old tags */ |
297 | for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) |
298 | intel_de_write(i915, FBC_TAG(i), val: 0); |
299 | |
300 | if (DISPLAY_VER(i915) == 4) { |
301 | intel_de_write(i915, FBC_CONTROL2, |
302 | val: i965_fbc_ctl2(fbc)); |
303 | intel_de_write(i915, FBC_FENCE_OFF, |
304 | val: fbc_state->fence_y_offset); |
305 | } |
306 | |
307 | intel_de_write(i915, FBC_CONTROL, |
308 | FBC_CTL_EN | i8xx_fbc_ctl(fbc)); |
309 | } |
310 | |
311 | static bool i8xx_fbc_is_active(struct intel_fbc *fbc) |
312 | { |
313 | return intel_de_read(i915: fbc->i915, FBC_CONTROL) & FBC_CTL_EN; |
314 | } |
315 | |
316 | static bool i8xx_fbc_is_compressing(struct intel_fbc *fbc) |
317 | { |
318 | return intel_de_read(i915: fbc->i915, FBC_STATUS) & |
319 | (FBC_STAT_COMPRESSING | FBC_STAT_COMPRESSED); |
320 | } |
321 | |
322 | static void i8xx_fbc_nuke(struct intel_fbc *fbc) |
323 | { |
324 | struct intel_fbc_state *fbc_state = &fbc->state; |
325 | enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; |
326 | struct drm_i915_private *dev_priv = fbc->i915; |
327 | |
328 | intel_de_write_fw(i915: dev_priv, DSPADDR(i9xx_plane), |
329 | val: intel_de_read_fw(i915: dev_priv, DSPADDR(i9xx_plane))); |
330 | } |
331 | |
332 | static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) |
333 | { |
334 | struct drm_i915_private *i915 = fbc->i915; |
335 | |
336 | drm_WARN_ON(&i915->drm, |
337 | range_overflows_end_t(u64, i915_gem_stolen_area_address(i915), |
338 | i915_gem_stolen_node_offset(&fbc->compressed_fb), |
339 | U32_MAX)); |
340 | drm_WARN_ON(&i915->drm, |
341 | range_overflows_end_t(u64, i915_gem_stolen_area_address(i915), |
342 | i915_gem_stolen_node_offset(&fbc->compressed_llb), |
343 | U32_MAX)); |
344 | intel_de_write(i915, FBC_CFB_BASE, |
345 | val: i915_gem_stolen_node_address(i915, node: &fbc->compressed_fb)); |
346 | intel_de_write(i915, FBC_LL_BASE, |
347 | val: i915_gem_stolen_node_address(i915, node: &fbc->compressed_llb)); |
348 | } |
349 | |
350 | static const struct intel_fbc_funcs i8xx_fbc_funcs = { |
351 | .activate = i8xx_fbc_activate, |
352 | .deactivate = i8xx_fbc_deactivate, |
353 | .is_active = i8xx_fbc_is_active, |
354 | .is_compressing = i8xx_fbc_is_compressing, |
355 | .nuke = i8xx_fbc_nuke, |
356 | .program_cfb = i8xx_fbc_program_cfb, |
357 | }; |
358 | |
359 | static void i965_fbc_nuke(struct intel_fbc *fbc) |
360 | { |
361 | struct intel_fbc_state *fbc_state = &fbc->state; |
362 | enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; |
363 | struct drm_i915_private *dev_priv = fbc->i915; |
364 | |
365 | intel_de_write_fw(i915: dev_priv, DSPSURF(i9xx_plane), |
366 | val: intel_de_read_fw(i915: dev_priv, DSPSURF(i9xx_plane))); |
367 | } |
368 | |
369 | static const struct intel_fbc_funcs i965_fbc_funcs = { |
370 | .activate = i8xx_fbc_activate, |
371 | .deactivate = i8xx_fbc_deactivate, |
372 | .is_active = i8xx_fbc_is_active, |
373 | .is_compressing = i8xx_fbc_is_compressing, |
374 | .nuke = i965_fbc_nuke, |
375 | .program_cfb = i8xx_fbc_program_cfb, |
376 | }; |
377 | |
378 | static u32 g4x_dpfc_ctl_limit(struct intel_fbc *fbc) |
379 | { |
380 | switch (fbc->limit) { |
381 | default: |
382 | MISSING_CASE(fbc->limit); |
383 | fallthrough; |
384 | case 1: |
385 | return DPFC_CTL_LIMIT_1X; |
386 | case 2: |
387 | return DPFC_CTL_LIMIT_2X; |
388 | case 4: |
389 | return DPFC_CTL_LIMIT_4X; |
390 | } |
391 | } |
392 | |
393 | static u32 g4x_dpfc_ctl(struct intel_fbc *fbc) |
394 | { |
395 | const struct intel_fbc_state *fbc_state = &fbc->state; |
396 | struct drm_i915_private *i915 = fbc->i915; |
397 | u32 dpfc_ctl; |
398 | |
399 | dpfc_ctl = g4x_dpfc_ctl_limit(fbc) | |
400 | DPFC_CTL_PLANE_G4X(fbc_state->plane->i9xx_plane); |
401 | |
402 | if (IS_G4X(i915)) |
403 | dpfc_ctl |= DPFC_CTL_SR_EN; |
404 | |
405 | if (fbc_state->fence_id >= 0) { |
406 | dpfc_ctl |= DPFC_CTL_FENCE_EN_G4X; |
407 | |
408 | if (DISPLAY_VER(i915) < 6) |
409 | dpfc_ctl |= DPFC_CTL_FENCENO(fbc_state->fence_id); |
410 | } |
411 | |
412 | return dpfc_ctl; |
413 | } |
414 | |
415 | static void g4x_fbc_activate(struct intel_fbc *fbc) |
416 | { |
417 | const struct intel_fbc_state *fbc_state = &fbc->state; |
418 | struct drm_i915_private *i915 = fbc->i915; |
419 | |
420 | intel_de_write(i915, DPFC_FENCE_YOFF, |
421 | val: fbc_state->fence_y_offset); |
422 | |
423 | intel_de_write(i915, DPFC_CONTROL, |
424 | DPFC_CTL_EN | g4x_dpfc_ctl(fbc)); |
425 | } |
426 | |
427 | static void g4x_fbc_deactivate(struct intel_fbc *fbc) |
428 | { |
429 | struct drm_i915_private *i915 = fbc->i915; |
430 | u32 dpfc_ctl; |
431 | |
432 | /* Disable compression */ |
433 | dpfc_ctl = intel_de_read(i915, DPFC_CONTROL); |
434 | if (dpfc_ctl & DPFC_CTL_EN) { |
435 | dpfc_ctl &= ~DPFC_CTL_EN; |
436 | intel_de_write(i915, DPFC_CONTROL, val: dpfc_ctl); |
437 | } |
438 | } |
439 | |
440 | static bool g4x_fbc_is_active(struct intel_fbc *fbc) |
441 | { |
442 | return intel_de_read(i915: fbc->i915, DPFC_CONTROL) & DPFC_CTL_EN; |
443 | } |
444 | |
445 | static bool g4x_fbc_is_compressing(struct intel_fbc *fbc) |
446 | { |
447 | return intel_de_read(i915: fbc->i915, DPFC_STATUS) & DPFC_COMP_SEG_MASK; |
448 | } |
449 | |
450 | static void g4x_fbc_program_cfb(struct intel_fbc *fbc) |
451 | { |
452 | struct drm_i915_private *i915 = fbc->i915; |
453 | |
454 | intel_de_write(i915, DPFC_CB_BASE, |
455 | val: i915_gem_stolen_node_offset(node: &fbc->compressed_fb)); |
456 | } |
457 | |
458 | static const struct intel_fbc_funcs g4x_fbc_funcs = { |
459 | .activate = g4x_fbc_activate, |
460 | .deactivate = g4x_fbc_deactivate, |
461 | .is_active = g4x_fbc_is_active, |
462 | .is_compressing = g4x_fbc_is_compressing, |
463 | .nuke = i965_fbc_nuke, |
464 | .program_cfb = g4x_fbc_program_cfb, |
465 | }; |
466 | |
467 | static void ilk_fbc_activate(struct intel_fbc *fbc) |
468 | { |
469 | struct intel_fbc_state *fbc_state = &fbc->state; |
470 | struct drm_i915_private *i915 = fbc->i915; |
471 | |
472 | intel_de_write(i915, ILK_DPFC_FENCE_YOFF(fbc->id), |
473 | val: fbc_state->fence_y_offset); |
474 | |
475 | intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), |
476 | DPFC_CTL_EN | g4x_dpfc_ctl(fbc)); |
477 | } |
478 | |
479 | static void ilk_fbc_deactivate(struct intel_fbc *fbc) |
480 | { |
481 | struct drm_i915_private *i915 = fbc->i915; |
482 | u32 dpfc_ctl; |
483 | |
484 | /* Disable compression */ |
485 | dpfc_ctl = intel_de_read(i915, ILK_DPFC_CONTROL(fbc->id)); |
486 | if (dpfc_ctl & DPFC_CTL_EN) { |
487 | dpfc_ctl &= ~DPFC_CTL_EN; |
488 | intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), val: dpfc_ctl); |
489 | } |
490 | } |
491 | |
492 | static bool ilk_fbc_is_active(struct intel_fbc *fbc) |
493 | { |
494 | return intel_de_read(i915: fbc->i915, ILK_DPFC_CONTROL(fbc->id)) & DPFC_CTL_EN; |
495 | } |
496 | |
497 | static bool ilk_fbc_is_compressing(struct intel_fbc *fbc) |
498 | { |
499 | return intel_de_read(i915: fbc->i915, ILK_DPFC_STATUS(fbc->id)) & DPFC_COMP_SEG_MASK; |
500 | } |
501 | |
502 | static void ilk_fbc_program_cfb(struct intel_fbc *fbc) |
503 | { |
504 | struct drm_i915_private *i915 = fbc->i915; |
505 | |
506 | intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id), |
507 | val: i915_gem_stolen_node_offset(node: &fbc->compressed_fb)); |
508 | } |
509 | |
510 | static const struct intel_fbc_funcs ilk_fbc_funcs = { |
511 | .activate = ilk_fbc_activate, |
512 | .deactivate = ilk_fbc_deactivate, |
513 | .is_active = ilk_fbc_is_active, |
514 | .is_compressing = ilk_fbc_is_compressing, |
515 | .nuke = i965_fbc_nuke, |
516 | .program_cfb = ilk_fbc_program_cfb, |
517 | }; |
518 | |
519 | static void snb_fbc_program_fence(struct intel_fbc *fbc) |
520 | { |
521 | const struct intel_fbc_state *fbc_state = &fbc->state; |
522 | struct drm_i915_private *i915 = fbc->i915; |
523 | u32 ctl = 0; |
524 | |
525 | if (fbc_state->fence_id >= 0) |
526 | ctl = SNB_DPFC_FENCE_EN | SNB_DPFC_FENCENO(fbc_state->fence_id); |
527 | |
528 | intel_de_write(i915, SNB_DPFC_CTL_SA, val: ctl); |
529 | intel_de_write(i915, SNB_DPFC_CPU_FENCE_OFFSET, val: fbc_state->fence_y_offset); |
530 | } |
531 | |
532 | static void snb_fbc_activate(struct intel_fbc *fbc) |
533 | { |
534 | snb_fbc_program_fence(fbc); |
535 | |
536 | ilk_fbc_activate(fbc); |
537 | } |
538 | |
539 | static void snb_fbc_nuke(struct intel_fbc *fbc) |
540 | { |
541 | struct drm_i915_private *i915 = fbc->i915; |
542 | |
543 | intel_de_write(i915, MSG_FBC_REND_STATE(fbc->id), FBC_REND_NUKE); |
544 | intel_de_posting_read(i915, MSG_FBC_REND_STATE(fbc->id)); |
545 | } |
546 | |
547 | static const struct intel_fbc_funcs snb_fbc_funcs = { |
548 | .activate = snb_fbc_activate, |
549 | .deactivate = ilk_fbc_deactivate, |
550 | .is_active = ilk_fbc_is_active, |
551 | .is_compressing = ilk_fbc_is_compressing, |
552 | .nuke = snb_fbc_nuke, |
553 | .program_cfb = ilk_fbc_program_cfb, |
554 | }; |
555 | |
556 | static void glk_fbc_program_cfb_stride(struct intel_fbc *fbc) |
557 | { |
558 | const struct intel_fbc_state *fbc_state = &fbc->state; |
559 | struct drm_i915_private *i915 = fbc->i915; |
560 | u32 val = 0; |
561 | |
562 | if (fbc_state->override_cfb_stride) |
563 | val |= FBC_STRIDE_OVERRIDE | |
564 | FBC_STRIDE(fbc_state->override_cfb_stride / fbc->limit); |
565 | |
566 | intel_de_write(i915, GLK_FBC_STRIDE(fbc->id), val); |
567 | } |
568 | |
569 | static void skl_fbc_program_cfb_stride(struct intel_fbc *fbc) |
570 | { |
571 | const struct intel_fbc_state *fbc_state = &fbc->state; |
572 | struct drm_i915_private *i915 = fbc->i915; |
573 | u32 val = 0; |
574 | |
575 | /* Display WA #0529: skl, kbl, bxt. */ |
576 | if (fbc_state->override_cfb_stride) |
577 | val |= CHICKEN_FBC_STRIDE_OVERRIDE | |
578 | CHICKEN_FBC_STRIDE(fbc_state->override_cfb_stride / fbc->limit); |
579 | |
580 | intel_de_rmw(i915, CHICKEN_MISC_4, |
581 | CHICKEN_FBC_STRIDE_OVERRIDE | |
582 | CHICKEN_FBC_STRIDE_MASK, set: val); |
583 | } |
584 | |
585 | static u32 ivb_dpfc_ctl(struct intel_fbc *fbc) |
586 | { |
587 | const struct intel_fbc_state *fbc_state = &fbc->state; |
588 | struct drm_i915_private *i915 = fbc->i915; |
589 | u32 dpfc_ctl; |
590 | |
591 | dpfc_ctl = g4x_dpfc_ctl_limit(fbc); |
592 | |
593 | if (IS_IVYBRIDGE(i915)) |
594 | dpfc_ctl |= DPFC_CTL_PLANE_IVB(fbc_state->plane->i9xx_plane); |
595 | |
596 | if (DISPLAY_VER(i915) >= 20) |
597 | dpfc_ctl |= DPFC_CTL_PLANE_BINDING(fbc_state->plane->id); |
598 | |
599 | if (fbc_state->fence_id >= 0) |
600 | dpfc_ctl |= DPFC_CTL_FENCE_EN_IVB; |
601 | |
602 | if (fbc->false_color) |
603 | dpfc_ctl |= DPFC_CTL_FALSE_COLOR; |
604 | |
605 | return dpfc_ctl; |
606 | } |
607 | |
608 | static void ivb_fbc_activate(struct intel_fbc *fbc) |
609 | { |
610 | struct drm_i915_private *i915 = fbc->i915; |
611 | u32 dpfc_ctl; |
612 | |
613 | if (DISPLAY_VER(i915) >= 10) |
614 | glk_fbc_program_cfb_stride(fbc); |
615 | else if (DISPLAY_VER(i915) == 9) |
616 | skl_fbc_program_cfb_stride(fbc); |
617 | |
618 | if (intel_gt_support_legacy_fencing(to_gt(i915))) |
619 | snb_fbc_program_fence(fbc); |
620 | |
621 | /* wa_14019417088 Alternative WA*/ |
622 | dpfc_ctl = ivb_dpfc_ctl(fbc); |
623 | if (DISPLAY_VER(i915) >= 20) |
624 | intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), val: dpfc_ctl); |
625 | |
626 | intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), |
627 | DPFC_CTL_EN | dpfc_ctl); |
628 | } |
629 | |
630 | static bool ivb_fbc_is_compressing(struct intel_fbc *fbc) |
631 | { |
632 | return intel_de_read(i915: fbc->i915, ILK_DPFC_STATUS2(fbc->id)) & DPFC_COMP_SEG_MASK_IVB; |
633 | } |
634 | |
635 | static void ivb_fbc_set_false_color(struct intel_fbc *fbc, |
636 | bool enable) |
637 | { |
638 | intel_de_rmw(i915: fbc->i915, ILK_DPFC_CONTROL(fbc->id), |
639 | DPFC_CTL_FALSE_COLOR, set: enable ? DPFC_CTL_FALSE_COLOR : 0); |
640 | } |
641 | |
642 | static const struct intel_fbc_funcs ivb_fbc_funcs = { |
643 | .activate = ivb_fbc_activate, |
644 | .deactivate = ilk_fbc_deactivate, |
645 | .is_active = ilk_fbc_is_active, |
646 | .is_compressing = ivb_fbc_is_compressing, |
647 | .nuke = snb_fbc_nuke, |
648 | .program_cfb = ilk_fbc_program_cfb, |
649 | .set_false_color = ivb_fbc_set_false_color, |
650 | }; |
651 | |
652 | static bool intel_fbc_hw_is_active(struct intel_fbc *fbc) |
653 | { |
654 | return fbc->funcs->is_active(fbc); |
655 | } |
656 | |
657 | static void intel_fbc_hw_activate(struct intel_fbc *fbc) |
658 | { |
659 | trace_intel_fbc_activate(plane: fbc->state.plane); |
660 | |
661 | fbc->active = true; |
662 | fbc->activated = true; |
663 | |
664 | fbc->funcs->activate(fbc); |
665 | } |
666 | |
667 | static void intel_fbc_hw_deactivate(struct intel_fbc *fbc) |
668 | { |
669 | trace_intel_fbc_deactivate(plane: fbc->state.plane); |
670 | |
671 | fbc->active = false; |
672 | |
673 | fbc->funcs->deactivate(fbc); |
674 | } |
675 | |
676 | static bool intel_fbc_is_compressing(struct intel_fbc *fbc) |
677 | { |
678 | return fbc->funcs->is_compressing(fbc); |
679 | } |
680 | |
681 | static void intel_fbc_nuke(struct intel_fbc *fbc) |
682 | { |
683 | struct drm_i915_private *i915 = fbc->i915; |
684 | |
685 | lockdep_assert_held(&fbc->lock); |
686 | drm_WARN_ON(&i915->drm, fbc->flip_pending); |
687 | |
688 | trace_intel_fbc_nuke(plane: fbc->state.plane); |
689 | |
690 | fbc->funcs->nuke(fbc); |
691 | } |
692 | |
693 | static void intel_fbc_activate(struct intel_fbc *fbc) |
694 | { |
695 | lockdep_assert_held(&fbc->lock); |
696 | |
697 | intel_fbc_hw_activate(fbc); |
698 | intel_fbc_nuke(fbc); |
699 | |
700 | fbc->no_fbc_reason = NULL; |
701 | } |
702 | |
703 | static void intel_fbc_deactivate(struct intel_fbc *fbc, const char *reason) |
704 | { |
705 | lockdep_assert_held(&fbc->lock); |
706 | |
707 | if (fbc->active) |
708 | intel_fbc_hw_deactivate(fbc); |
709 | |
710 | fbc->no_fbc_reason = reason; |
711 | } |
712 | |
713 | static u64 intel_fbc_cfb_base_max(struct drm_i915_private *i915) |
714 | { |
715 | if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) |
716 | return BIT_ULL(28); |
717 | else |
718 | return BIT_ULL(32); |
719 | } |
720 | |
721 | static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) |
722 | { |
723 | u64 end; |
724 | |
725 | /* The FBC hardware for BDW/SKL doesn't have access to the stolen |
726 | * reserved range size, so it always assumes the maximum (8mb) is used. |
727 | * If we enable FBC using a CFB on that memory range we'll get FIFO |
728 | * underruns, even if that range is not reserved by the BIOS. */ |
729 | if (IS_BROADWELL(i915) || |
730 | (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915))) |
731 | end = i915_gem_stolen_area_size(i915) - 8 * 1024 * 1024; |
732 | else |
733 | end = U64_MAX; |
734 | |
735 | return min(end, intel_fbc_cfb_base_max(i915)); |
736 | } |
737 | |
738 | static int intel_fbc_min_limit(const struct intel_plane_state *plane_state) |
739 | { |
740 | return plane_state->hw.fb->format->cpp[0] == 2 ? 2 : 1; |
741 | } |
742 | |
743 | static int intel_fbc_max_limit(struct drm_i915_private *i915) |
744 | { |
745 | /* WaFbcOnly1to1Ratio:ctg */ |
746 | if (IS_G4X(i915)) |
747 | return 1; |
748 | |
749 | /* |
750 | * FBC2 can only do 1:1, 1:2, 1:4, we limit |
751 | * FBC1 to the same out of convenience. |
752 | */ |
753 | return 4; |
754 | } |
755 | |
756 | static int find_compression_limit(struct intel_fbc *fbc, |
757 | unsigned int size, int min_limit) |
758 | { |
759 | struct drm_i915_private *i915 = fbc->i915; |
760 | u64 end = intel_fbc_stolen_end(i915); |
761 | int ret, limit = min_limit; |
762 | |
763 | size /= limit; |
764 | |
765 | /* Try to over-allocate to reduce reallocations and fragmentation. */ |
766 | ret = i915_gem_stolen_insert_node_in_range(dev_priv: i915, node: &fbc->compressed_fb, |
767 | size: size <<= 1, alignment: 4096, start: 0, end); |
768 | if (ret == 0) |
769 | return limit; |
770 | |
771 | for (; limit <= intel_fbc_max_limit(i915); limit <<= 1) { |
772 | ret = i915_gem_stolen_insert_node_in_range(dev_priv: i915, node: &fbc->compressed_fb, |
773 | size: size >>= 1, alignment: 4096, start: 0, end); |
774 | if (ret == 0) |
775 | return limit; |
776 | } |
777 | |
778 | return 0; |
779 | } |
780 | |
781 | static int intel_fbc_alloc_cfb(struct intel_fbc *fbc, |
782 | unsigned int size, int min_limit) |
783 | { |
784 | struct drm_i915_private *i915 = fbc->i915; |
785 | int ret; |
786 | |
787 | drm_WARN_ON(&i915->drm, |
788 | i915_gem_stolen_node_allocated(&fbc->compressed_fb)); |
789 | drm_WARN_ON(&i915->drm, |
790 | i915_gem_stolen_node_allocated(&fbc->compressed_llb)); |
791 | |
792 | if (DISPLAY_VER(i915) < 5 && !IS_G4X(i915)) { |
793 | ret = i915_gem_stolen_insert_node(dev_priv: i915, node: &fbc->compressed_llb, |
794 | size: 4096, alignment: 4096); |
795 | if (ret) |
796 | goto err; |
797 | } |
798 | |
799 | ret = find_compression_limit(fbc, size, min_limit); |
800 | if (!ret) |
801 | goto err_llb; |
802 | else if (ret > min_limit) |
803 | drm_info_once(&i915->drm, |
804 | "Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n" ); |
805 | |
806 | fbc->limit = ret; |
807 | |
808 | drm_dbg_kms(&i915->drm, |
809 | "reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n" , |
810 | i915_gem_stolen_node_size(&fbc->compressed_fb), fbc->limit); |
811 | return 0; |
812 | |
813 | err_llb: |
814 | if (i915_gem_stolen_node_allocated(node: &fbc->compressed_llb)) |
815 | i915_gem_stolen_remove_node(dev_priv: i915, node: &fbc->compressed_llb); |
816 | err: |
817 | if (i915_gem_stolen_initialized(i915)) |
818 | drm_info_once(&i915->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n" , size); |
819 | return -ENOSPC; |
820 | } |
821 | |
822 | static void intel_fbc_program_cfb(struct intel_fbc *fbc) |
823 | { |
824 | fbc->funcs->program_cfb(fbc); |
825 | } |
826 | |
827 | static void intel_fbc_program_workarounds(struct intel_fbc *fbc) |
828 | { |
829 | /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp,mtl */ |
830 | if (DISPLAY_VER(fbc->i915) >= 11 && !IS_DG2(fbc->i915)) |
831 | intel_de_rmw(i915: fbc->i915, ILK_DPFC_CHICKEN(fbc->id), clear: 0, |
832 | DPFC_CHICKEN_FORCE_SLB_INVALIDATION); |
833 | } |
834 | |
835 | static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) |
836 | { |
837 | struct drm_i915_private *i915 = fbc->i915; |
838 | |
839 | if (WARN_ON(intel_fbc_hw_is_active(fbc))) |
840 | return; |
841 | |
842 | if (i915_gem_stolen_node_allocated(node: &fbc->compressed_llb)) |
843 | i915_gem_stolen_remove_node(dev_priv: i915, node: &fbc->compressed_llb); |
844 | if (i915_gem_stolen_node_allocated(node: &fbc->compressed_fb)) |
845 | i915_gem_stolen_remove_node(dev_priv: i915, node: &fbc->compressed_fb); |
846 | } |
847 | |
848 | void intel_fbc_cleanup(struct drm_i915_private *i915) |
849 | { |
850 | struct intel_fbc *fbc; |
851 | enum intel_fbc_id fbc_id; |
852 | |
853 | for_each_intel_fbc(i915, fbc, fbc_id) { |
854 | mutex_lock(&fbc->lock); |
855 | __intel_fbc_cleanup_cfb(fbc); |
856 | mutex_unlock(lock: &fbc->lock); |
857 | |
858 | kfree(objp: fbc); |
859 | } |
860 | } |
861 | |
862 | static bool i8xx_fbc_stride_is_valid(const struct intel_plane_state *plane_state) |
863 | { |
864 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
865 | unsigned int stride = intel_fbc_plane_stride(plane_state) * |
866 | fb->format->cpp[0]; |
867 | |
868 | return stride == 4096 || stride == 8192; |
869 | } |
870 | |
871 | static bool i965_fbc_stride_is_valid(const struct intel_plane_state *plane_state) |
872 | { |
873 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
874 | unsigned int stride = intel_fbc_plane_stride(plane_state) * |
875 | fb->format->cpp[0]; |
876 | |
877 | return stride >= 2048 && stride <= 16384; |
878 | } |
879 | |
880 | static bool g4x_fbc_stride_is_valid(const struct intel_plane_state *plane_state) |
881 | { |
882 | return true; |
883 | } |
884 | |
885 | static bool skl_fbc_stride_is_valid(const struct intel_plane_state *plane_state) |
886 | { |
887 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
888 | unsigned int stride = intel_fbc_plane_stride(plane_state) * |
889 | fb->format->cpp[0]; |
890 | |
891 | /* Display WA #1105: skl,bxt,kbl,cfl,glk */ |
892 | if (fb->modifier == DRM_FORMAT_MOD_LINEAR && stride & 511) |
893 | return false; |
894 | |
895 | return true; |
896 | } |
897 | |
898 | static bool icl_fbc_stride_is_valid(const struct intel_plane_state *plane_state) |
899 | { |
900 | return true; |
901 | } |
902 | |
903 | static bool stride_is_valid(const struct intel_plane_state *plane_state) |
904 | { |
905 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
906 | |
907 | if (DISPLAY_VER(i915) >= 11) |
908 | return icl_fbc_stride_is_valid(plane_state); |
909 | else if (DISPLAY_VER(i915) >= 9) |
910 | return skl_fbc_stride_is_valid(plane_state); |
911 | else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) |
912 | return g4x_fbc_stride_is_valid(plane_state); |
913 | else if (DISPLAY_VER(i915) == 4) |
914 | return i965_fbc_stride_is_valid(plane_state); |
915 | else |
916 | return i8xx_fbc_stride_is_valid(plane_state); |
917 | } |
918 | |
919 | static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) |
920 | { |
921 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
922 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
923 | |
924 | switch (fb->format->format) { |
925 | case DRM_FORMAT_XRGB8888: |
926 | case DRM_FORMAT_XBGR8888: |
927 | return true; |
928 | case DRM_FORMAT_XRGB1555: |
929 | case DRM_FORMAT_RGB565: |
930 | /* 16bpp not supported on gen2 */ |
931 | if (DISPLAY_VER(i915) == 2) |
932 | return false; |
933 | return true; |
934 | default: |
935 | return false; |
936 | } |
937 | } |
938 | |
939 | static bool g4x_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) |
940 | { |
941 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
942 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
943 | |
944 | switch (fb->format->format) { |
945 | case DRM_FORMAT_XRGB8888: |
946 | case DRM_FORMAT_XBGR8888: |
947 | return true; |
948 | case DRM_FORMAT_RGB565: |
949 | /* WaFbcOnly1to1Ratio:ctg */ |
950 | if (IS_G4X(i915)) |
951 | return false; |
952 | return true; |
953 | default: |
954 | return false; |
955 | } |
956 | } |
957 | |
958 | static bool lnl_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) |
959 | { |
960 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
961 | |
962 | switch (fb->format->format) { |
963 | case DRM_FORMAT_XRGB8888: |
964 | case DRM_FORMAT_XBGR8888: |
965 | case DRM_FORMAT_ARGB8888: |
966 | case DRM_FORMAT_ABGR8888: |
967 | case DRM_FORMAT_RGB565: |
968 | return true; |
969 | default: |
970 | return false; |
971 | } |
972 | } |
973 | |
974 | static bool pixel_format_is_valid(const struct intel_plane_state *plane_state) |
975 | { |
976 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
977 | |
978 | if (DISPLAY_VER(i915) >= 20) |
979 | return lnl_fbc_pixel_format_is_valid(plane_state); |
980 | else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) |
981 | return g4x_fbc_pixel_format_is_valid(plane_state); |
982 | else |
983 | return i8xx_fbc_pixel_format_is_valid(plane_state); |
984 | } |
985 | |
986 | static bool i8xx_fbc_rotation_is_valid(const struct intel_plane_state *plane_state) |
987 | { |
988 | return plane_state->hw.rotation == DRM_MODE_ROTATE_0; |
989 | } |
990 | |
991 | static bool g4x_fbc_rotation_is_valid(const struct intel_plane_state *plane_state) |
992 | { |
993 | return true; |
994 | } |
995 | |
996 | static bool skl_fbc_rotation_is_valid(const struct intel_plane_state *plane_state) |
997 | { |
998 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
999 | unsigned int rotation = plane_state->hw.rotation; |
1000 | |
1001 | if (fb->format->format == DRM_FORMAT_RGB565 && |
1002 | drm_rotation_90_or_270(rotation)) |
1003 | return false; |
1004 | |
1005 | return true; |
1006 | } |
1007 | |
1008 | static bool rotation_is_valid(const struct intel_plane_state *plane_state) |
1009 | { |
1010 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
1011 | |
1012 | if (DISPLAY_VER(i915) >= 9) |
1013 | return skl_fbc_rotation_is_valid(plane_state); |
1014 | else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) |
1015 | return g4x_fbc_rotation_is_valid(plane_state); |
1016 | else |
1017 | return i8xx_fbc_rotation_is_valid(plane_state); |
1018 | } |
1019 | |
1020 | /* |
1021 | * For some reason, the hardware tracking starts looking at whatever we |
1022 | * programmed as the display plane base address register. It does not look at |
1023 | * the X and Y offset registers. That's why we include the src x/y offsets |
1024 | * instead of just looking at the plane size. |
1025 | */ |
1026 | static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state *plane_state) |
1027 | { |
1028 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
1029 | unsigned int effective_w, effective_h, max_w, max_h; |
1030 | |
1031 | if (DISPLAY_VER(i915) >= 11) { |
1032 | max_w = 8192; |
1033 | max_h = 4096; |
1034 | } else if (DISPLAY_VER(i915) >= 10) { |
1035 | max_w = 5120; |
1036 | max_h = 4096; |
1037 | } else if (DISPLAY_VER(i915) >= 7) { |
1038 | max_w = 4096; |
1039 | max_h = 4096; |
1040 | } else if (IS_G4X(i915) || DISPLAY_VER(i915) >= 5) { |
1041 | max_w = 4096; |
1042 | max_h = 2048; |
1043 | } else { |
1044 | max_w = 2048; |
1045 | max_h = 1536; |
1046 | } |
1047 | |
1048 | effective_w = plane_state->view.color_plane[0].x + |
1049 | (drm_rect_width(r: &plane_state->uapi.src) >> 16); |
1050 | effective_h = plane_state->view.color_plane[0].y + |
1051 | (drm_rect_height(r: &plane_state->uapi.src) >> 16); |
1052 | |
1053 | return effective_w <= max_w && effective_h <= max_h; |
1054 | } |
1055 | |
1056 | static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state) |
1057 | { |
1058 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
1059 | unsigned int w, h, max_w, max_h; |
1060 | |
1061 | if (DISPLAY_VER(i915) >= 10) { |
1062 | max_w = 5120; |
1063 | max_h = 4096; |
1064 | } else if (DISPLAY_VER(i915) >= 8 || IS_HASWELL(i915)) { |
1065 | max_w = 4096; |
1066 | max_h = 4096; |
1067 | } else if (IS_G4X(i915) || DISPLAY_VER(i915) >= 5) { |
1068 | max_w = 4096; |
1069 | max_h = 2048; |
1070 | } else { |
1071 | max_w = 2048; |
1072 | max_h = 1536; |
1073 | } |
1074 | |
1075 | w = drm_rect_width(r: &plane_state->uapi.src) >> 16; |
1076 | h = drm_rect_height(r: &plane_state->uapi.src) >> 16; |
1077 | |
1078 | return w <= max_w && h <= max_h; |
1079 | } |
1080 | |
1081 | static bool i8xx_fbc_tiling_valid(const struct intel_plane_state *plane_state) |
1082 | { |
1083 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
1084 | |
1085 | return fb->modifier == I915_FORMAT_MOD_X_TILED; |
1086 | } |
1087 | |
1088 | static bool skl_fbc_tiling_valid(const struct intel_plane_state *plane_state) |
1089 | { |
1090 | return true; |
1091 | } |
1092 | |
1093 | static bool tiling_is_valid(const struct intel_plane_state *plane_state) |
1094 | { |
1095 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
1096 | |
1097 | if (DISPLAY_VER(i915) >= 9) |
1098 | return skl_fbc_tiling_valid(plane_state); |
1099 | else |
1100 | return i8xx_fbc_tiling_valid(plane_state); |
1101 | } |
1102 | |
1103 | static void intel_fbc_update_state(struct intel_atomic_state *state, |
1104 | struct intel_crtc *crtc, |
1105 | struct intel_plane *plane) |
1106 | { |
1107 | struct drm_i915_private *i915 = to_i915(dev: state->base.dev); |
1108 | const struct intel_crtc_state *crtc_state = |
1109 | intel_atomic_get_new_crtc_state(state, crtc); |
1110 | const struct intel_plane_state *plane_state = |
1111 | intel_atomic_get_new_plane_state(state, plane); |
1112 | struct intel_fbc *fbc = plane->fbc; |
1113 | struct intel_fbc_state *fbc_state = &fbc->state; |
1114 | |
1115 | WARN_ON(plane_state->no_fbc_reason); |
1116 | WARN_ON(fbc_state->plane && fbc_state->plane != plane); |
1117 | |
1118 | fbc_state->plane = plane; |
1119 | |
1120 | /* FBC1 compression interval: arbitrary choice of 1 second */ |
1121 | fbc_state->interval = drm_mode_vrefresh(mode: &crtc_state->hw.adjusted_mode); |
1122 | |
1123 | fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state); |
1124 | |
1125 | drm_WARN_ON(&i915->drm, plane_state->flags & PLANE_HAS_FENCE && |
1126 | !intel_gt_support_legacy_fencing(to_gt(i915))); |
1127 | |
1128 | if (plane_state->flags & PLANE_HAS_FENCE) |
1129 | fbc_state->fence_id = i915_vma_fence_id(vma: plane_state->ggtt_vma); |
1130 | else |
1131 | fbc_state->fence_id = -1; |
1132 | |
1133 | fbc_state->cfb_stride = intel_fbc_cfb_stride(plane_state); |
1134 | fbc_state->cfb_size = intel_fbc_cfb_size(plane_state); |
1135 | fbc_state->override_cfb_stride = intel_fbc_override_cfb_stride(plane_state); |
1136 | } |
1137 | |
1138 | static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state) |
1139 | { |
1140 | struct drm_i915_private *i915 = to_i915(dev: plane_state->uapi.plane->dev); |
1141 | |
1142 | /* |
1143 | * The use of a CPU fence is one of two ways to detect writes by the |
1144 | * CPU to the scanout and trigger updates to the FBC. |
1145 | * |
1146 | * The other method is by software tracking (see |
1147 | * intel_fbc_invalidate/flush()), it will manually notify FBC and nuke |
1148 | * the current compressed buffer and recompress it. |
1149 | * |
1150 | * Note that is possible for a tiled surface to be unmappable (and |
1151 | * so have no fence associated with it) due to aperture constraints |
1152 | * at the time of pinning. |
1153 | */ |
1154 | return DISPLAY_VER(i915) >= 9 || |
1155 | (plane_state->flags & PLANE_HAS_FENCE && |
1156 | i915_vma_fence_id(vma: plane_state->ggtt_vma) != -1); |
1157 | } |
1158 | |
1159 | static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state) |
1160 | { |
1161 | struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); |
1162 | struct intel_fbc *fbc = plane->fbc; |
1163 | |
1164 | return intel_fbc_min_limit(plane_state) <= fbc->limit && |
1165 | intel_fbc_cfb_size(plane_state) <= fbc->limit * |
1166 | i915_gem_stolen_node_size(node: &fbc->compressed_fb); |
1167 | } |
1168 | |
1169 | static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state) |
1170 | { |
1171 | return !plane_state->no_fbc_reason && |
1172 | intel_fbc_is_fence_ok(plane_state) && |
1173 | intel_fbc_is_cfb_ok(plane_state); |
1174 | } |
1175 | |
1176 | static int intel_fbc_check_plane(struct intel_atomic_state *state, |
1177 | struct intel_plane *plane) |
1178 | { |
1179 | struct drm_i915_private *i915 = to_i915(dev: state->base.dev); |
1180 | struct intel_plane_state *plane_state = |
1181 | intel_atomic_get_new_plane_state(state, plane); |
1182 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
1183 | struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); |
1184 | const struct intel_crtc_state *crtc_state; |
1185 | struct intel_fbc *fbc = plane->fbc; |
1186 | |
1187 | if (!fbc) |
1188 | return 0; |
1189 | |
1190 | if (!i915_gem_stolen_initialized(i915)) { |
1191 | plane_state->no_fbc_reason = "stolen memory not initialised" ; |
1192 | return 0; |
1193 | } |
1194 | |
1195 | if (intel_vgpu_active(i915)) { |
1196 | plane_state->no_fbc_reason = "VGPU active" ; |
1197 | return 0; |
1198 | } |
1199 | |
1200 | if (!i915->display.params.enable_fbc) { |
1201 | plane_state->no_fbc_reason = "disabled per module param or by default" ; |
1202 | return 0; |
1203 | } |
1204 | |
1205 | if (!plane_state->uapi.visible) { |
1206 | plane_state->no_fbc_reason = "plane not visible" ; |
1207 | return 0; |
1208 | } |
1209 | |
1210 | crtc_state = intel_atomic_get_new_crtc_state(state, crtc); |
1211 | |
1212 | if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { |
1213 | plane_state->no_fbc_reason = "interlaced mode not supported" ; |
1214 | return 0; |
1215 | } |
1216 | |
1217 | if (crtc_state->double_wide) { |
1218 | plane_state->no_fbc_reason = "double wide pipe not supported" ; |
1219 | return 0; |
1220 | } |
1221 | |
1222 | /* |
1223 | * Display 12+ is not supporting FBC with PSR2. |
1224 | * Recommendation is to keep this combination disabled |
1225 | * Bspec: 50422 HSD: 14010260002 |
1226 | */ |
1227 | if (IS_DISPLAY_VER(i915, 12, 14) && crtc_state->has_psr2) { |
1228 | plane_state->no_fbc_reason = "PSR2 enabled" ; |
1229 | return 0; |
1230 | } |
1231 | |
1232 | /* Wa_14016291713 */ |
1233 | if ((IS_DISPLAY_VER(i915, 12, 13) || |
1234 | IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0)) && |
1235 | crtc_state->has_psr) { |
1236 | plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)" ; |
1237 | return 0; |
1238 | } |
1239 | |
1240 | if (!pixel_format_is_valid(plane_state)) { |
1241 | plane_state->no_fbc_reason = "pixel format not supported" ; |
1242 | return 0; |
1243 | } |
1244 | |
1245 | if (!tiling_is_valid(plane_state)) { |
1246 | plane_state->no_fbc_reason = "tiling not supported" ; |
1247 | return 0; |
1248 | } |
1249 | |
1250 | if (!rotation_is_valid(plane_state)) { |
1251 | plane_state->no_fbc_reason = "rotation not supported" ; |
1252 | return 0; |
1253 | } |
1254 | |
1255 | if (!stride_is_valid(plane_state)) { |
1256 | plane_state->no_fbc_reason = "stride not supported" ; |
1257 | return 0; |
1258 | } |
1259 | |
1260 | if (DISPLAY_VER(i915) < 20 && |
1261 | plane_state->hw.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE && |
1262 | fb->format->has_alpha) { |
1263 | plane_state->no_fbc_reason = "per-pixel alpha not supported" ; |
1264 | return 0; |
1265 | } |
1266 | |
1267 | if (!intel_fbc_plane_size_valid(plane_state)) { |
1268 | plane_state->no_fbc_reason = "plane size too big" ; |
1269 | return 0; |
1270 | } |
1271 | |
1272 | if (!intel_fbc_hw_tracking_covers_screen(plane_state)) { |
1273 | plane_state->no_fbc_reason = "surface size too big" ; |
1274 | return 0; |
1275 | } |
1276 | |
1277 | /* |
1278 | * Work around a problem on GEN9+ HW, where enabling FBC on a plane |
1279 | * having a Y offset that isn't divisible by 4 causes FIFO underrun |
1280 | * and screen flicker. |
1281 | */ |
1282 | if (DISPLAY_VER(i915) >= 9 && |
1283 | plane_state->view.color_plane[0].y & 3) { |
1284 | plane_state->no_fbc_reason = "plane start Y offset misaligned" ; |
1285 | return 0; |
1286 | } |
1287 | |
1288 | /* Wa_22010751166: icl, ehl, tgl, dg1, rkl */ |
1289 | if (DISPLAY_VER(i915) >= 11 && |
1290 | (plane_state->view.color_plane[0].y + |
1291 | (drm_rect_height(r: &plane_state->uapi.src) >> 16)) & 3) { |
1292 | plane_state->no_fbc_reason = "plane end Y offset misaligned" ; |
1293 | return 0; |
1294 | } |
1295 | |
1296 | /* WaFbcExceedCdClockThreshold:hsw,bdw */ |
1297 | if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { |
1298 | const struct intel_cdclk_state *cdclk_state; |
1299 | |
1300 | cdclk_state = intel_atomic_get_cdclk_state(state); |
1301 | if (IS_ERR(ptr: cdclk_state)) |
1302 | return PTR_ERR(ptr: cdclk_state); |
1303 | |
1304 | if (crtc_state->pixel_rate >= cdclk_state->logical.cdclk * 95 / 100) { |
1305 | plane_state->no_fbc_reason = "pixel rate too high" ; |
1306 | return 0; |
1307 | } |
1308 | } |
1309 | |
1310 | plane_state->no_fbc_reason = NULL; |
1311 | |
1312 | return 0; |
1313 | } |
1314 | |
1315 | |
1316 | static bool intel_fbc_can_flip_nuke(struct intel_atomic_state *state, |
1317 | struct intel_crtc *crtc, |
1318 | struct intel_plane *plane) |
1319 | { |
1320 | const struct intel_crtc_state *new_crtc_state = |
1321 | intel_atomic_get_new_crtc_state(state, crtc); |
1322 | const struct intel_plane_state *old_plane_state = |
1323 | intel_atomic_get_old_plane_state(state, plane); |
1324 | const struct intel_plane_state *new_plane_state = |
1325 | intel_atomic_get_new_plane_state(state, plane); |
1326 | const struct drm_framebuffer *old_fb = old_plane_state->hw.fb; |
1327 | const struct drm_framebuffer *new_fb = new_plane_state->hw.fb; |
1328 | |
1329 | if (intel_crtc_needs_modeset(crtc_state: new_crtc_state)) |
1330 | return false; |
1331 | |
1332 | if (!intel_fbc_is_ok(plane_state: old_plane_state) || |
1333 | !intel_fbc_is_ok(plane_state: new_plane_state)) |
1334 | return false; |
1335 | |
1336 | if (old_fb->format->format != new_fb->format->format) |
1337 | return false; |
1338 | |
1339 | if (old_fb->modifier != new_fb->modifier) |
1340 | return false; |
1341 | |
1342 | if (intel_fbc_plane_stride(plane_state: old_plane_state) != |
1343 | intel_fbc_plane_stride(plane_state: new_plane_state)) |
1344 | return false; |
1345 | |
1346 | if (intel_fbc_cfb_stride(plane_state: old_plane_state) != |
1347 | intel_fbc_cfb_stride(plane_state: new_plane_state)) |
1348 | return false; |
1349 | |
1350 | if (intel_fbc_cfb_size(plane_state: old_plane_state) != |
1351 | intel_fbc_cfb_size(plane_state: new_plane_state)) |
1352 | return false; |
1353 | |
1354 | if (intel_fbc_override_cfb_stride(plane_state: old_plane_state) != |
1355 | intel_fbc_override_cfb_stride(plane_state: new_plane_state)) |
1356 | return false; |
1357 | |
1358 | return true; |
1359 | } |
1360 | |
1361 | static bool __intel_fbc_pre_update(struct intel_atomic_state *state, |
1362 | struct intel_crtc *crtc, |
1363 | struct intel_plane *plane) |
1364 | { |
1365 | struct drm_i915_private *i915 = to_i915(dev: state->base.dev); |
1366 | struct intel_fbc *fbc = plane->fbc; |
1367 | bool need_vblank_wait = false; |
1368 | |
1369 | lockdep_assert_held(&fbc->lock); |
1370 | |
1371 | fbc->flip_pending = true; |
1372 | |
1373 | if (intel_fbc_can_flip_nuke(state, crtc, plane)) |
1374 | return need_vblank_wait; |
1375 | |
1376 | intel_fbc_deactivate(fbc, reason: "update pending" ); |
1377 | |
1378 | /* |
1379 | * Display WA #1198: glk+ |
1380 | * Need an extra vblank wait between FBC disable and most plane |
1381 | * updates. Bspec says this is only needed for plane disable, but |
1382 | * that is not true. Touching most plane registers will cause the |
1383 | * corruption to appear. Also SKL/derivatives do not seem to be |
1384 | * affected. |
1385 | * |
1386 | * TODO: could optimize this a bit by sampling the frame |
1387 | * counter when we disable FBC (if it was already done earlier) |
1388 | * and skipping the extra vblank wait before the plane update |
1389 | * if at least one frame has already passed. |
1390 | */ |
1391 | if (fbc->activated && DISPLAY_VER(i915) >= 10) |
1392 | need_vblank_wait = true; |
1393 | fbc->activated = false; |
1394 | |
1395 | return need_vblank_wait; |
1396 | } |
1397 | |
1398 | bool intel_fbc_pre_update(struct intel_atomic_state *state, |
1399 | struct intel_crtc *crtc) |
1400 | { |
1401 | const struct intel_plane_state __maybe_unused *plane_state; |
1402 | bool need_vblank_wait = false; |
1403 | struct intel_plane *plane; |
1404 | int i; |
1405 | |
1406 | for_each_new_intel_plane_in_state(state, plane, plane_state, i) { |
1407 | struct intel_fbc *fbc = plane->fbc; |
1408 | |
1409 | if (!fbc || plane->pipe != crtc->pipe) |
1410 | continue; |
1411 | |
1412 | mutex_lock(&fbc->lock); |
1413 | |
1414 | if (fbc->state.plane == plane) |
1415 | need_vblank_wait |= __intel_fbc_pre_update(state, crtc, plane); |
1416 | |
1417 | mutex_unlock(lock: &fbc->lock); |
1418 | } |
1419 | |
1420 | return need_vblank_wait; |
1421 | } |
1422 | |
1423 | static void __intel_fbc_disable(struct intel_fbc *fbc) |
1424 | { |
1425 | struct drm_i915_private *i915 = fbc->i915; |
1426 | struct intel_plane *plane = fbc->state.plane; |
1427 | |
1428 | lockdep_assert_held(&fbc->lock); |
1429 | drm_WARN_ON(&i915->drm, fbc->active); |
1430 | |
1431 | drm_dbg_kms(&i915->drm, "Disabling FBC on [PLANE:%d:%s]\n" , |
1432 | plane->base.base.id, plane->base.name); |
1433 | |
1434 | __intel_fbc_cleanup_cfb(fbc); |
1435 | |
1436 | fbc->state.plane = NULL; |
1437 | fbc->flip_pending = false; |
1438 | fbc->busy_bits = 0; |
1439 | } |
1440 | |
1441 | static void __intel_fbc_post_update(struct intel_fbc *fbc) |
1442 | { |
1443 | lockdep_assert_held(&fbc->lock); |
1444 | |
1445 | fbc->flip_pending = false; |
1446 | fbc->busy_bits = 0; |
1447 | |
1448 | intel_fbc_activate(fbc); |
1449 | } |
1450 | |
1451 | void intel_fbc_post_update(struct intel_atomic_state *state, |
1452 | struct intel_crtc *crtc) |
1453 | { |
1454 | const struct intel_plane_state __maybe_unused *plane_state; |
1455 | struct intel_plane *plane; |
1456 | int i; |
1457 | |
1458 | for_each_new_intel_plane_in_state(state, plane, plane_state, i) { |
1459 | struct intel_fbc *fbc = plane->fbc; |
1460 | |
1461 | if (!fbc || plane->pipe != crtc->pipe) |
1462 | continue; |
1463 | |
1464 | mutex_lock(&fbc->lock); |
1465 | |
1466 | if (fbc->state.plane == plane) |
1467 | __intel_fbc_post_update(fbc); |
1468 | |
1469 | mutex_unlock(lock: &fbc->lock); |
1470 | } |
1471 | } |
1472 | |
1473 | static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc) |
1474 | { |
1475 | if (fbc->state.plane) |
1476 | return fbc->state.plane->frontbuffer_bit; |
1477 | else |
1478 | return 0; |
1479 | } |
1480 | |
1481 | static void __intel_fbc_invalidate(struct intel_fbc *fbc, |
1482 | unsigned int frontbuffer_bits, |
1483 | enum fb_op_origin origin) |
1484 | { |
1485 | if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE) |
1486 | return; |
1487 | |
1488 | mutex_lock(&fbc->lock); |
1489 | |
1490 | frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc); |
1491 | if (!frontbuffer_bits) |
1492 | goto out; |
1493 | |
1494 | fbc->busy_bits |= frontbuffer_bits; |
1495 | intel_fbc_deactivate(fbc, reason: "frontbuffer write" ); |
1496 | |
1497 | out: |
1498 | mutex_unlock(lock: &fbc->lock); |
1499 | } |
1500 | |
1501 | void intel_fbc_invalidate(struct drm_i915_private *i915, |
1502 | unsigned int frontbuffer_bits, |
1503 | enum fb_op_origin origin) |
1504 | { |
1505 | struct intel_fbc *fbc; |
1506 | enum intel_fbc_id fbc_id; |
1507 | |
1508 | for_each_intel_fbc(i915, fbc, fbc_id) |
1509 | __intel_fbc_invalidate(fbc, frontbuffer_bits, origin); |
1510 | |
1511 | } |
1512 | |
1513 | static void __intel_fbc_flush(struct intel_fbc *fbc, |
1514 | unsigned int frontbuffer_bits, |
1515 | enum fb_op_origin origin) |
1516 | { |
1517 | mutex_lock(&fbc->lock); |
1518 | |
1519 | frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc); |
1520 | if (!frontbuffer_bits) |
1521 | goto out; |
1522 | |
1523 | fbc->busy_bits &= ~frontbuffer_bits; |
1524 | |
1525 | if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE) |
1526 | goto out; |
1527 | |
1528 | if (fbc->busy_bits || fbc->flip_pending) |
1529 | goto out; |
1530 | |
1531 | if (fbc->active) |
1532 | intel_fbc_nuke(fbc); |
1533 | else |
1534 | intel_fbc_activate(fbc); |
1535 | |
1536 | out: |
1537 | mutex_unlock(lock: &fbc->lock); |
1538 | } |
1539 | |
1540 | void intel_fbc_flush(struct drm_i915_private *i915, |
1541 | unsigned int frontbuffer_bits, |
1542 | enum fb_op_origin origin) |
1543 | { |
1544 | struct intel_fbc *fbc; |
1545 | enum intel_fbc_id fbc_id; |
1546 | |
1547 | for_each_intel_fbc(i915, fbc, fbc_id) |
1548 | __intel_fbc_flush(fbc, frontbuffer_bits, origin); |
1549 | } |
1550 | |
1551 | int intel_fbc_atomic_check(struct intel_atomic_state *state) |
1552 | { |
1553 | struct intel_plane_state __maybe_unused *plane_state; |
1554 | struct intel_plane *plane; |
1555 | int i; |
1556 | |
1557 | for_each_new_intel_plane_in_state(state, plane, plane_state, i) { |
1558 | int ret; |
1559 | |
1560 | ret = intel_fbc_check_plane(state, plane); |
1561 | if (ret) |
1562 | return ret; |
1563 | } |
1564 | |
1565 | return 0; |
1566 | } |
1567 | |
1568 | static void __intel_fbc_enable(struct intel_atomic_state *state, |
1569 | struct intel_crtc *crtc, |
1570 | struct intel_plane *plane) |
1571 | { |
1572 | struct drm_i915_private *i915 = to_i915(dev: state->base.dev); |
1573 | const struct intel_plane_state *plane_state = |
1574 | intel_atomic_get_new_plane_state(state, plane); |
1575 | struct intel_fbc *fbc = plane->fbc; |
1576 | |
1577 | lockdep_assert_held(&fbc->lock); |
1578 | |
1579 | if (fbc->state.plane) { |
1580 | if (fbc->state.plane != plane) |
1581 | return; |
1582 | |
1583 | if (intel_fbc_is_ok(plane_state)) { |
1584 | intel_fbc_update_state(state, crtc, plane); |
1585 | return; |
1586 | } |
1587 | |
1588 | __intel_fbc_disable(fbc); |
1589 | } |
1590 | |
1591 | drm_WARN_ON(&i915->drm, fbc->active); |
1592 | |
1593 | fbc->no_fbc_reason = plane_state->no_fbc_reason; |
1594 | if (fbc->no_fbc_reason) |
1595 | return; |
1596 | |
1597 | if (!intel_fbc_is_fence_ok(plane_state)) { |
1598 | fbc->no_fbc_reason = "framebuffer not fenced" ; |
1599 | return; |
1600 | } |
1601 | |
1602 | if (fbc->underrun_detected) { |
1603 | fbc->no_fbc_reason = "FIFO underrun" ; |
1604 | return; |
1605 | } |
1606 | |
1607 | if (intel_fbc_alloc_cfb(fbc, size: intel_fbc_cfb_size(plane_state), |
1608 | min_limit: intel_fbc_min_limit(plane_state))) { |
1609 | fbc->no_fbc_reason = "not enough stolen memory" ; |
1610 | return; |
1611 | } |
1612 | |
1613 | drm_dbg_kms(&i915->drm, "Enabling FBC on [PLANE:%d:%s]\n" , |
1614 | plane->base.base.id, plane->base.name); |
1615 | fbc->no_fbc_reason = "FBC enabled but not active yet\n" ; |
1616 | |
1617 | intel_fbc_update_state(state, crtc, plane); |
1618 | |
1619 | intel_fbc_program_workarounds(fbc); |
1620 | intel_fbc_program_cfb(fbc); |
1621 | } |
1622 | |
1623 | /** |
1624 | * intel_fbc_disable - disable FBC if it's associated with crtc |
1625 | * @crtc: the CRTC |
1626 | * |
1627 | * This function disables FBC if it's associated with the provided CRTC. |
1628 | */ |
1629 | void intel_fbc_disable(struct intel_crtc *crtc) |
1630 | { |
1631 | struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev); |
1632 | struct intel_plane *plane; |
1633 | |
1634 | for_each_intel_plane(&i915->drm, plane) { |
1635 | struct intel_fbc *fbc = plane->fbc; |
1636 | |
1637 | if (!fbc || plane->pipe != crtc->pipe) |
1638 | continue; |
1639 | |
1640 | mutex_lock(&fbc->lock); |
1641 | if (fbc->state.plane == plane) |
1642 | __intel_fbc_disable(fbc); |
1643 | mutex_unlock(lock: &fbc->lock); |
1644 | } |
1645 | } |
1646 | |
1647 | void intel_fbc_update(struct intel_atomic_state *state, |
1648 | struct intel_crtc *crtc) |
1649 | { |
1650 | const struct intel_crtc_state *crtc_state = |
1651 | intel_atomic_get_new_crtc_state(state, crtc); |
1652 | const struct intel_plane_state *plane_state; |
1653 | struct intel_plane *plane; |
1654 | int i; |
1655 | |
1656 | for_each_new_intel_plane_in_state(state, plane, plane_state, i) { |
1657 | struct intel_fbc *fbc = plane->fbc; |
1658 | |
1659 | if (!fbc || plane->pipe != crtc->pipe) |
1660 | continue; |
1661 | |
1662 | mutex_lock(&fbc->lock); |
1663 | |
1664 | if (intel_crtc_needs_fastset(crtc_state) && |
1665 | plane_state->no_fbc_reason) { |
1666 | if (fbc->state.plane == plane) |
1667 | __intel_fbc_disable(fbc); |
1668 | } else { |
1669 | __intel_fbc_enable(state, crtc, plane); |
1670 | } |
1671 | |
1672 | mutex_unlock(lock: &fbc->lock); |
1673 | } |
1674 | } |
1675 | |
1676 | static void intel_fbc_underrun_work_fn(struct work_struct *work) |
1677 | { |
1678 | struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work); |
1679 | struct drm_i915_private *i915 = fbc->i915; |
1680 | |
1681 | mutex_lock(&fbc->lock); |
1682 | |
1683 | /* Maybe we were scheduled twice. */ |
1684 | if (fbc->underrun_detected || !fbc->state.plane) |
1685 | goto out; |
1686 | |
1687 | drm_dbg_kms(&i915->drm, "Disabling FBC due to FIFO underrun.\n" ); |
1688 | fbc->underrun_detected = true; |
1689 | |
1690 | intel_fbc_deactivate(fbc, reason: "FIFO underrun" ); |
1691 | if (!fbc->flip_pending) |
1692 | intel_crtc_wait_for_next_vblank(crtc: intel_crtc_for_pipe(i915, pipe: fbc->state.plane->pipe)); |
1693 | __intel_fbc_disable(fbc); |
1694 | out: |
1695 | mutex_unlock(lock: &fbc->lock); |
1696 | } |
1697 | |
1698 | static void __intel_fbc_reset_underrun(struct intel_fbc *fbc) |
1699 | { |
1700 | struct drm_i915_private *i915 = fbc->i915; |
1701 | |
1702 | cancel_work_sync(work: &fbc->underrun_work); |
1703 | |
1704 | mutex_lock(&fbc->lock); |
1705 | |
1706 | if (fbc->underrun_detected) { |
1707 | drm_dbg_kms(&i915->drm, |
1708 | "Re-allowing FBC after fifo underrun\n" ); |
1709 | fbc->no_fbc_reason = "FIFO underrun cleared" ; |
1710 | } |
1711 | |
1712 | fbc->underrun_detected = false; |
1713 | mutex_unlock(lock: &fbc->lock); |
1714 | } |
1715 | |
1716 | /* |
1717 | * intel_fbc_reset_underrun - reset FBC fifo underrun status. |
1718 | * @i915: the i915 device |
1719 | * |
1720 | * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we |
1721 | * want to re-enable FBC after an underrun to increase test coverage. |
1722 | */ |
1723 | void intel_fbc_reset_underrun(struct drm_i915_private *i915) |
1724 | { |
1725 | struct intel_fbc *fbc; |
1726 | enum intel_fbc_id fbc_id; |
1727 | |
1728 | for_each_intel_fbc(i915, fbc, fbc_id) |
1729 | __intel_fbc_reset_underrun(fbc); |
1730 | } |
1731 | |
1732 | static void __intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc) |
1733 | { |
1734 | /* |
1735 | * There's no guarantee that underrun_detected won't be set to true |
1736 | * right after this check and before the work is scheduled, but that's |
1737 | * not a problem since we'll check it again under the work function |
1738 | * while FBC is locked. This check here is just to prevent us from |
1739 | * unnecessarily scheduling the work, and it relies on the fact that we |
1740 | * never switch underrun_detect back to false after it's true. |
1741 | */ |
1742 | if (READ_ONCE(fbc->underrun_detected)) |
1743 | return; |
1744 | |
1745 | queue_work(wq: fbc->i915->unordered_wq, work: &fbc->underrun_work); |
1746 | } |
1747 | |
1748 | /** |
1749 | * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun |
1750 | * @i915: i915 device |
1751 | * |
1752 | * Without FBC, most underruns are harmless and don't really cause too many |
1753 | * problems, except for an annoying message on dmesg. With FBC, underruns can |
1754 | * become black screens or even worse, especially when paired with bad |
1755 | * watermarks. So in order for us to be on the safe side, completely disable FBC |
1756 | * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe |
1757 | * already suggests that watermarks may be bad, so try to be as safe as |
1758 | * possible. |
1759 | * |
1760 | * This function is called from the IRQ handler. |
1761 | */ |
1762 | void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915) |
1763 | { |
1764 | struct intel_fbc *fbc; |
1765 | enum intel_fbc_id fbc_id; |
1766 | |
1767 | for_each_intel_fbc(i915, fbc, fbc_id) |
1768 | __intel_fbc_handle_fifo_underrun_irq(fbc); |
1769 | } |
1770 | |
1771 | /* |
1772 | * The DDX driver changes its behavior depending on the value it reads from |
1773 | * i915.enable_fbc, so sanitize it by translating the default value into either |
1774 | * 0 or 1 in order to allow it to know what's going on. |
1775 | * |
1776 | * Notice that this is done at driver initialization and we still allow user |
1777 | * space to change the value during runtime without sanitizing it again. IGT |
1778 | * relies on being able to change i915.enable_fbc at runtime. |
1779 | */ |
1780 | static int intel_sanitize_fbc_option(struct drm_i915_private *i915) |
1781 | { |
1782 | if (i915->display.params.enable_fbc >= 0) |
1783 | return !!i915->display.params.enable_fbc; |
1784 | |
1785 | if (!HAS_FBC(i915)) |
1786 | return 0; |
1787 | |
1788 | if (IS_BROADWELL(i915) || DISPLAY_VER(i915) >= 9) |
1789 | return 1; |
1790 | |
1791 | return 0; |
1792 | } |
1793 | |
1794 | static bool need_fbc_vtd_wa(struct drm_i915_private *i915) |
1795 | { |
1796 | /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ |
1797 | if (i915_vtd_active(i915) && |
1798 | (IS_SKYLAKE(i915) || IS_BROXTON(i915))) { |
1799 | drm_info(&i915->drm, |
1800 | "Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n" ); |
1801 | return true; |
1802 | } |
1803 | |
1804 | return false; |
1805 | } |
1806 | |
1807 | void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane) |
1808 | { |
1809 | plane->fbc = fbc; |
1810 | } |
1811 | |
1812 | static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915, |
1813 | enum intel_fbc_id fbc_id) |
1814 | { |
1815 | struct intel_fbc *fbc; |
1816 | |
1817 | fbc = kzalloc(size: sizeof(*fbc), GFP_KERNEL); |
1818 | if (!fbc) |
1819 | return NULL; |
1820 | |
1821 | fbc->id = fbc_id; |
1822 | fbc->i915 = i915; |
1823 | INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); |
1824 | mutex_init(&fbc->lock); |
1825 | |
1826 | if (DISPLAY_VER(i915) >= 7) |
1827 | fbc->funcs = &ivb_fbc_funcs; |
1828 | else if (DISPLAY_VER(i915) == 6) |
1829 | fbc->funcs = &snb_fbc_funcs; |
1830 | else if (DISPLAY_VER(i915) == 5) |
1831 | fbc->funcs = &ilk_fbc_funcs; |
1832 | else if (IS_G4X(i915)) |
1833 | fbc->funcs = &g4x_fbc_funcs; |
1834 | else if (DISPLAY_VER(i915) == 4) |
1835 | fbc->funcs = &i965_fbc_funcs; |
1836 | else |
1837 | fbc->funcs = &i8xx_fbc_funcs; |
1838 | |
1839 | return fbc; |
1840 | } |
1841 | |
1842 | /** |
1843 | * intel_fbc_init - Initialize FBC |
1844 | * @i915: the i915 device |
1845 | * |
1846 | * This function might be called during PM init process. |
1847 | */ |
1848 | void intel_fbc_init(struct drm_i915_private *i915) |
1849 | { |
1850 | enum intel_fbc_id fbc_id; |
1851 | |
1852 | if (need_fbc_vtd_wa(i915)) |
1853 | DISPLAY_RUNTIME_INFO(i915)->fbc_mask = 0; |
1854 | |
1855 | i915->display.params.enable_fbc = intel_sanitize_fbc_option(i915); |
1856 | drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n" , |
1857 | i915->display.params.enable_fbc); |
1858 | |
1859 | for_each_fbc_id(i915, fbc_id) |
1860 | i915->display.fbc[fbc_id] = intel_fbc_create(i915, fbc_id); |
1861 | } |
1862 | |
1863 | /** |
1864 | * intel_fbc_sanitize - Sanitize FBC |
1865 | * @i915: the i915 device |
1866 | * |
1867 | * Make sure FBC is initially disabled since we have no |
1868 | * idea eg. into which parts of stolen it might be scribbling |
1869 | * into. |
1870 | */ |
1871 | void intel_fbc_sanitize(struct drm_i915_private *i915) |
1872 | { |
1873 | struct intel_fbc *fbc; |
1874 | enum intel_fbc_id fbc_id; |
1875 | |
1876 | for_each_intel_fbc(i915, fbc, fbc_id) { |
1877 | if (intel_fbc_hw_is_active(fbc)) |
1878 | intel_fbc_hw_deactivate(fbc); |
1879 | } |
1880 | } |
1881 | |
1882 | static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused) |
1883 | { |
1884 | struct intel_fbc *fbc = m->private; |
1885 | struct drm_i915_private *i915 = fbc->i915; |
1886 | struct intel_plane *plane; |
1887 | intel_wakeref_t wakeref; |
1888 | |
1889 | drm_modeset_lock_all(dev: &i915->drm); |
1890 | |
1891 | wakeref = intel_runtime_pm_get(rpm: &i915->runtime_pm); |
1892 | mutex_lock(&fbc->lock); |
1893 | |
1894 | if (fbc->active) { |
1895 | seq_puts(m, s: "FBC enabled\n" ); |
1896 | seq_printf(m, fmt: "Compressing: %s\n" , |
1897 | str_yes_no(v: intel_fbc_is_compressing(fbc))); |
1898 | } else { |
1899 | seq_printf(m, fmt: "FBC disabled: %s\n" , fbc->no_fbc_reason); |
1900 | } |
1901 | |
1902 | for_each_intel_plane(&i915->drm, plane) { |
1903 | const struct intel_plane_state *plane_state = |
1904 | to_intel_plane_state(plane->base.state); |
1905 | |
1906 | if (plane->fbc != fbc) |
1907 | continue; |
1908 | |
1909 | seq_printf(m, fmt: "%c [PLANE:%d:%s]: %s\n" , |
1910 | fbc->state.plane == plane ? '*' : ' ', |
1911 | plane->base.base.id, plane->base.name, |
1912 | plane_state->no_fbc_reason ?: "FBC possible" ); |
1913 | } |
1914 | |
1915 | mutex_unlock(lock: &fbc->lock); |
1916 | intel_runtime_pm_put(rpm: &i915->runtime_pm, wref: wakeref); |
1917 | |
1918 | drm_modeset_unlock_all(dev: &i915->drm); |
1919 | |
1920 | return 0; |
1921 | } |
1922 | |
1923 | DEFINE_SHOW_ATTRIBUTE(intel_fbc_debugfs_status); |
1924 | |
1925 | static int intel_fbc_debugfs_false_color_get(void *data, u64 *val) |
1926 | { |
1927 | struct intel_fbc *fbc = data; |
1928 | |
1929 | *val = fbc->false_color; |
1930 | |
1931 | return 0; |
1932 | } |
1933 | |
1934 | static int intel_fbc_debugfs_false_color_set(void *data, u64 val) |
1935 | { |
1936 | struct intel_fbc *fbc = data; |
1937 | |
1938 | mutex_lock(&fbc->lock); |
1939 | |
1940 | fbc->false_color = val; |
1941 | |
1942 | if (fbc->active) |
1943 | fbc->funcs->set_false_color(fbc, fbc->false_color); |
1944 | |
1945 | mutex_unlock(lock: &fbc->lock); |
1946 | |
1947 | return 0; |
1948 | } |
1949 | |
1950 | DEFINE_DEBUGFS_ATTRIBUTE(intel_fbc_debugfs_false_color_fops, |
1951 | intel_fbc_debugfs_false_color_get, |
1952 | intel_fbc_debugfs_false_color_set, |
1953 | "%llu\n" ); |
1954 | |
1955 | static void intel_fbc_debugfs_add(struct intel_fbc *fbc, |
1956 | struct dentry *parent) |
1957 | { |
1958 | debugfs_create_file(name: "i915_fbc_status" , mode: 0444, parent, |
1959 | data: fbc, fops: &intel_fbc_debugfs_status_fops); |
1960 | |
1961 | if (fbc->funcs->set_false_color) |
1962 | debugfs_create_file_unsafe(name: "i915_fbc_false_color" , mode: 0644, parent, |
1963 | data: fbc, fops: &intel_fbc_debugfs_false_color_fops); |
1964 | } |
1965 | |
1966 | void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc) |
1967 | { |
1968 | struct intel_plane *plane = to_intel_plane(crtc->base.primary); |
1969 | |
1970 | if (plane->fbc) |
1971 | intel_fbc_debugfs_add(fbc: plane->fbc, parent: crtc->base.debugfs_entry); |
1972 | } |
1973 | |
1974 | /* FIXME: remove this once igt is on board with per-crtc stuff */ |
1975 | void intel_fbc_debugfs_register(struct drm_i915_private *i915) |
1976 | { |
1977 | struct drm_minor *minor = i915->drm.primary; |
1978 | struct intel_fbc *fbc; |
1979 | |
1980 | fbc = i915->display.fbc[INTEL_FBC_A]; |
1981 | if (fbc) |
1982 | intel_fbc_debugfs_add(fbc, parent: minor->debugfs_root); |
1983 | } |
1984 | |