Line data Source code
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 "intel_drv.h"
42 : #include "i915_drv.h"
43 :
44 0 : static inline bool fbc_supported(struct drm_i915_private *dev_priv)
45 : {
46 0 : return dev_priv->fbc.enable_fbc != NULL;
47 : }
48 :
49 : /*
50 : * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the
51 : * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's
52 : * origin so the x and y offsets can actually fit the registers. As a
53 : * consequence, the fence doesn't really start exactly at the display plane
54 : * address we program because it starts at the real start of the buffer, so we
55 : * have to take this into consideration here.
56 : */
57 0 : static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
58 : {
59 0 : return crtc->base.y - crtc->adjusted_y;
60 : }
61 :
62 0 : static void i8xx_fbc_disable(struct drm_i915_private *dev_priv)
63 : {
64 : u32 fbc_ctl;
65 :
66 0 : dev_priv->fbc.enabled = false;
67 :
68 : /* Disable compression */
69 0 : fbc_ctl = I915_READ(FBC_CONTROL);
70 0 : if ((fbc_ctl & FBC_CTL_EN) == 0)
71 0 : return;
72 :
73 0 : fbc_ctl &= ~FBC_CTL_EN;
74 0 : I915_WRITE(FBC_CONTROL, fbc_ctl);
75 :
76 : /* Wait for compressing bit to clear */
77 0 : if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
78 : DRM_DEBUG_KMS("FBC idle timed out\n");
79 0 : return;
80 : }
81 :
82 : DRM_DEBUG_KMS("disabled FBC\n");
83 0 : }
84 :
85 0 : static void i8xx_fbc_enable(struct intel_crtc *crtc)
86 : {
87 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
88 0 : struct drm_framebuffer *fb = crtc->base.primary->fb;
89 0 : struct drm_i915_gem_object *obj = intel_fb_obj(fb);
90 : int cfb_pitch;
91 : int i;
92 : u32 fbc_ctl;
93 :
94 0 : dev_priv->fbc.enabled = true;
95 :
96 : /* Note: fbc.threshold == 1 for i8xx */
97 0 : cfb_pitch = dev_priv->fbc.uncompressed_size / FBC_LL_SIZE;
98 0 : if (fb->pitches[0] < cfb_pitch)
99 0 : cfb_pitch = fb->pitches[0];
100 :
101 : /* FBC_CTL wants 32B or 64B units */
102 0 : if (IS_GEN2(dev_priv))
103 0 : cfb_pitch = (cfb_pitch / 32) - 1;
104 : else
105 0 : cfb_pitch = (cfb_pitch / 64) - 1;
106 :
107 : /* Clear old tags */
108 0 : for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
109 0 : I915_WRITE(FBC_TAG(i), 0);
110 :
111 0 : if (IS_GEN4(dev_priv)) {
112 : u32 fbc_ctl2;
113 :
114 : /* Set it up... */
115 : fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
116 0 : fbc_ctl2 |= FBC_CTL_PLANE(crtc->plane);
117 0 : I915_WRITE(FBC_CONTROL2, fbc_ctl2);
118 0 : I915_WRITE(FBC_FENCE_OFF, get_crtc_fence_y_offset(crtc));
119 0 : }
120 :
121 : /* enable it... */
122 0 : fbc_ctl = I915_READ(FBC_CONTROL);
123 0 : fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT;
124 0 : fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
125 0 : if (IS_I945GM(dev_priv))
126 0 : fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
127 0 : fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
128 0 : fbc_ctl |= obj->fence_reg;
129 0 : I915_WRITE(FBC_CONTROL, fbc_ctl);
130 :
131 : DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c\n",
132 : cfb_pitch, crtc->base.y, plane_name(crtc->plane));
133 0 : }
134 :
135 0 : static bool i8xx_fbc_enabled(struct drm_i915_private *dev_priv)
136 : {
137 0 : return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
138 : }
139 :
140 0 : static void g4x_fbc_enable(struct intel_crtc *crtc)
141 : {
142 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
143 0 : struct drm_framebuffer *fb = crtc->base.primary->fb;
144 0 : struct drm_i915_gem_object *obj = intel_fb_obj(fb);
145 : u32 dpfc_ctl;
146 :
147 0 : dev_priv->fbc.enabled = true;
148 :
149 0 : dpfc_ctl = DPFC_CTL_PLANE(crtc->plane) | DPFC_SR_EN;
150 0 : if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
151 0 : dpfc_ctl |= DPFC_CTL_LIMIT_2X;
152 : else
153 : dpfc_ctl |= DPFC_CTL_LIMIT_1X;
154 0 : dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
155 :
156 0 : I915_WRITE(DPFC_FENCE_YOFF, get_crtc_fence_y_offset(crtc));
157 :
158 : /* enable it... */
159 0 : I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
160 :
161 : DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
162 0 : }
163 :
164 0 : static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
165 : {
166 : u32 dpfc_ctl;
167 :
168 0 : dev_priv->fbc.enabled = false;
169 :
170 : /* Disable compression */
171 0 : dpfc_ctl = I915_READ(DPFC_CONTROL);
172 0 : if (dpfc_ctl & DPFC_CTL_EN) {
173 0 : dpfc_ctl &= ~DPFC_CTL_EN;
174 0 : I915_WRITE(DPFC_CONTROL, dpfc_ctl);
175 :
176 : DRM_DEBUG_KMS("disabled FBC\n");
177 0 : }
178 0 : }
179 :
180 0 : static bool g4x_fbc_enabled(struct drm_i915_private *dev_priv)
181 : {
182 0 : return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
183 : }
184 :
185 0 : static void intel_fbc_nuke(struct drm_i915_private *dev_priv)
186 : {
187 0 : I915_WRITE(MSG_FBC_REND_STATE, FBC_REND_NUKE);
188 0 : POSTING_READ(MSG_FBC_REND_STATE);
189 0 : }
190 :
191 0 : static void ilk_fbc_enable(struct intel_crtc *crtc)
192 : {
193 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
194 0 : struct drm_framebuffer *fb = crtc->base.primary->fb;
195 0 : struct drm_i915_gem_object *obj = intel_fb_obj(fb);
196 : u32 dpfc_ctl;
197 0 : int threshold = dev_priv->fbc.threshold;
198 : unsigned int y_offset;
199 :
200 0 : dev_priv->fbc.enabled = true;
201 :
202 0 : dpfc_ctl = DPFC_CTL_PLANE(crtc->plane);
203 0 : if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
204 0 : threshold++;
205 :
206 0 : switch (threshold) {
207 : case 4:
208 : case 3:
209 0 : dpfc_ctl |= DPFC_CTL_LIMIT_4X;
210 0 : break;
211 : case 2:
212 0 : dpfc_ctl |= DPFC_CTL_LIMIT_2X;
213 0 : break;
214 : case 1:
215 : dpfc_ctl |= DPFC_CTL_LIMIT_1X;
216 0 : break;
217 : }
218 0 : dpfc_ctl |= DPFC_CTL_FENCE_EN;
219 0 : if (IS_GEN5(dev_priv))
220 0 : dpfc_ctl |= obj->fence_reg;
221 :
222 0 : y_offset = get_crtc_fence_y_offset(crtc);
223 0 : I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset);
224 0 : I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
225 : /* enable it... */
226 0 : I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
227 :
228 0 : if (IS_GEN6(dev_priv)) {
229 0 : I915_WRITE(SNB_DPFC_CTL_SA,
230 : SNB_CPU_FENCE_ENABLE | obj->fence_reg);
231 0 : I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset);
232 0 : }
233 :
234 0 : intel_fbc_nuke(dev_priv);
235 :
236 : DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
237 0 : }
238 :
239 0 : static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
240 : {
241 : u32 dpfc_ctl;
242 :
243 0 : dev_priv->fbc.enabled = false;
244 :
245 : /* Disable compression */
246 0 : dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
247 0 : if (dpfc_ctl & DPFC_CTL_EN) {
248 0 : dpfc_ctl &= ~DPFC_CTL_EN;
249 0 : I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
250 :
251 : DRM_DEBUG_KMS("disabled FBC\n");
252 0 : }
253 0 : }
254 :
255 0 : static bool ilk_fbc_enabled(struct drm_i915_private *dev_priv)
256 : {
257 0 : return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
258 : }
259 :
260 0 : static void gen7_fbc_enable(struct intel_crtc *crtc)
261 : {
262 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
263 0 : struct drm_framebuffer *fb = crtc->base.primary->fb;
264 0 : struct drm_i915_gem_object *obj = intel_fb_obj(fb);
265 : u32 dpfc_ctl;
266 0 : int threshold = dev_priv->fbc.threshold;
267 :
268 0 : dev_priv->fbc.enabled = true;
269 :
270 : dpfc_ctl = 0;
271 0 : if (IS_IVYBRIDGE(dev_priv))
272 0 : dpfc_ctl |= IVB_DPFC_CTL_PLANE(crtc->plane);
273 :
274 0 : if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
275 0 : threshold++;
276 :
277 0 : switch (threshold) {
278 : case 4:
279 : case 3:
280 0 : dpfc_ctl |= DPFC_CTL_LIMIT_4X;
281 0 : break;
282 : case 2:
283 0 : dpfc_ctl |= DPFC_CTL_LIMIT_2X;
284 0 : break;
285 : case 1:
286 : dpfc_ctl |= DPFC_CTL_LIMIT_1X;
287 0 : break;
288 : }
289 :
290 0 : dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
291 :
292 0 : if (dev_priv->fbc.false_color)
293 0 : dpfc_ctl |= FBC_CTL_FALSE_COLOR;
294 :
295 0 : if (IS_IVYBRIDGE(dev_priv)) {
296 : /* WaFbcAsynchFlipDisableFbcQueue:ivb */
297 0 : I915_WRITE(ILK_DISPLAY_CHICKEN1,
298 : I915_READ(ILK_DISPLAY_CHICKEN1) |
299 : ILK_FBCQ_DIS);
300 0 : } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
301 : /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
302 0 : I915_WRITE(CHICKEN_PIPESL_1(crtc->pipe),
303 : I915_READ(CHICKEN_PIPESL_1(crtc->pipe)) |
304 : HSW_FBCQ_DIS);
305 0 : }
306 :
307 0 : I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
308 :
309 0 : I915_WRITE(SNB_DPFC_CTL_SA,
310 : SNB_CPU_FENCE_ENABLE | obj->fence_reg);
311 0 : I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc));
312 :
313 0 : intel_fbc_nuke(dev_priv);
314 :
315 : DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
316 0 : }
317 :
318 : /**
319 : * intel_fbc_enabled - Is FBC enabled?
320 : * @dev_priv: i915 device instance
321 : *
322 : * This function is used to verify the current state of FBC.
323 : * FIXME: This should be tracked in the plane config eventually
324 : * instead of queried at runtime for most callers.
325 : */
326 0 : bool intel_fbc_enabled(struct drm_i915_private *dev_priv)
327 : {
328 0 : return dev_priv->fbc.enabled;
329 : }
330 :
331 0 : static void intel_fbc_enable(struct intel_crtc *crtc,
332 : const struct drm_framebuffer *fb)
333 : {
334 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
335 :
336 0 : dev_priv->fbc.enable_fbc(crtc);
337 :
338 0 : dev_priv->fbc.crtc = crtc;
339 0 : dev_priv->fbc.fb_id = fb->base.id;
340 0 : dev_priv->fbc.y = crtc->base.y;
341 0 : }
342 :
343 0 : static void intel_fbc_work_fn(struct work_struct *__work)
344 : {
345 : struct intel_fbc_work *work =
346 0 : container_of(to_delayed_work(__work),
347 : struct intel_fbc_work, work);
348 0 : struct drm_i915_private *dev_priv = work->crtc->base.dev->dev_private;
349 0 : struct drm_framebuffer *crtc_fb = work->crtc->base.primary->fb;
350 :
351 0 : mutex_lock(&dev_priv->fbc.lock);
352 0 : if (work == dev_priv->fbc.fbc_work) {
353 : /* Double check that we haven't switched fb without cancelling
354 : * the prior work.
355 : */
356 0 : if (crtc_fb == work->fb)
357 0 : intel_fbc_enable(work->crtc, work->fb);
358 :
359 0 : dev_priv->fbc.fbc_work = NULL;
360 0 : }
361 0 : mutex_unlock(&dev_priv->fbc.lock);
362 :
363 0 : kfree(work);
364 0 : }
365 :
366 0 : static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
367 : {
368 0 : WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
369 :
370 0 : if (dev_priv->fbc.fbc_work == NULL)
371 : return;
372 :
373 : DRM_DEBUG_KMS("cancelling pending FBC enable\n");
374 :
375 : /* Synchronisation is provided by struct_mutex and checking of
376 : * dev_priv->fbc.fbc_work, so we can perform the cancellation
377 : * entirely asynchronously.
378 : */
379 0 : if (cancel_delayed_work(&dev_priv->fbc.fbc_work->work))
380 : /* tasklet was killed before being run, clean up */
381 0 : kfree(dev_priv->fbc.fbc_work);
382 :
383 : /* Mark the work as no longer wanted so that if it does
384 : * wake-up (because the work was already running and waiting
385 : * for our mutex), it will discover that is no longer
386 : * necessary to run.
387 : */
388 0 : dev_priv->fbc.fbc_work = NULL;
389 0 : }
390 :
391 0 : static void intel_fbc_schedule_enable(struct intel_crtc *crtc)
392 : {
393 : struct intel_fbc_work *work;
394 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
395 :
396 0 : WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
397 :
398 0 : intel_fbc_cancel_work(dev_priv);
399 :
400 0 : work = kzalloc(sizeof(*work), GFP_KERNEL);
401 0 : if (work == NULL) {
402 0 : DRM_ERROR("Failed to allocate FBC work structure\n");
403 0 : intel_fbc_enable(crtc, crtc->base.primary->fb);
404 0 : return;
405 : }
406 :
407 0 : work->crtc = crtc;
408 0 : work->fb = crtc->base.primary->fb;
409 0 : INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
410 :
411 0 : dev_priv->fbc.fbc_work = work;
412 :
413 : /* Delay the actual enabling to let pageflipping cease and the
414 : * display to settle before starting the compression. Note that
415 : * this delay also serves a second purpose: it allows for a
416 : * vblank to pass after disabling the FBC before we attempt
417 : * to modify the control registers.
418 : *
419 : * A more complicated solution would involve tracking vblanks
420 : * following the termination of the page-flipping sequence
421 : * and indeed performing the enable as a co-routine and not
422 : * waiting synchronously upon the vblank.
423 : *
424 : * WaFbcWaitForVBlankBeforeEnable:ilk,snb
425 : */
426 0 : schedule_delayed_work(&work->work, msecs_to_jiffies(50));
427 0 : }
428 :
429 0 : static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
430 : {
431 0 : WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
432 :
433 0 : intel_fbc_cancel_work(dev_priv);
434 :
435 0 : dev_priv->fbc.disable_fbc(dev_priv);
436 0 : dev_priv->fbc.crtc = NULL;
437 0 : }
438 :
439 : /**
440 : * intel_fbc_disable - disable FBC
441 : * @dev_priv: i915 device instance
442 : *
443 : * This function disables FBC.
444 : */
445 0 : void intel_fbc_disable(struct drm_i915_private *dev_priv)
446 : {
447 0 : if (!fbc_supported(dev_priv))
448 : return;
449 :
450 0 : mutex_lock(&dev_priv->fbc.lock);
451 0 : __intel_fbc_disable(dev_priv);
452 0 : mutex_unlock(&dev_priv->fbc.lock);
453 0 : }
454 :
455 : /*
456 : * intel_fbc_disable_crtc - disable FBC if it's associated with crtc
457 : * @crtc: the CRTC
458 : *
459 : * This function disables FBC if it's associated with the provided CRTC.
460 : */
461 0 : void intel_fbc_disable_crtc(struct intel_crtc *crtc)
462 : {
463 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
464 :
465 0 : if (!fbc_supported(dev_priv))
466 0 : return;
467 :
468 0 : mutex_lock(&dev_priv->fbc.lock);
469 0 : if (dev_priv->fbc.crtc == crtc)
470 0 : __intel_fbc_disable(dev_priv);
471 0 : mutex_unlock(&dev_priv->fbc.lock);
472 0 : }
473 :
474 0 : const char *intel_no_fbc_reason_str(enum no_fbc_reason reason)
475 : {
476 0 : switch (reason) {
477 : case FBC_OK:
478 0 : return "FBC enabled but currently disabled in hardware";
479 : case FBC_UNSUPPORTED:
480 0 : return "unsupported by this chipset";
481 : case FBC_NO_OUTPUT:
482 0 : return "no output";
483 : case FBC_STOLEN_TOO_SMALL:
484 0 : return "not enough stolen memory";
485 : case FBC_UNSUPPORTED_MODE:
486 0 : return "mode incompatible with compression";
487 : case FBC_MODE_TOO_LARGE:
488 0 : return "mode too large for compression";
489 : case FBC_BAD_PLANE:
490 0 : return "FBC unsupported on plane";
491 : case FBC_NOT_TILED:
492 0 : return "framebuffer not tiled or fenced";
493 : case FBC_MULTIPLE_PIPES:
494 0 : return "more than one pipe active";
495 : case FBC_MODULE_PARAM:
496 0 : return "disabled per module param";
497 : case FBC_CHIP_DEFAULT:
498 0 : return "disabled per chip default";
499 : case FBC_ROTATION:
500 0 : return "rotation unsupported";
501 : case FBC_IN_DBG_MASTER:
502 0 : return "Kernel debugger is active";
503 : case FBC_BAD_STRIDE:
504 0 : return "framebuffer stride not supported";
505 : case FBC_PIXEL_RATE:
506 0 : return "pixel rate is too big";
507 : case FBC_PIXEL_FORMAT:
508 0 : return "pixel format is invalid";
509 : default:
510 0 : MISSING_CASE(reason);
511 0 : return "unknown reason";
512 : }
513 0 : }
514 :
515 0 : static void set_no_fbc_reason(struct drm_i915_private *dev_priv,
516 : enum no_fbc_reason reason)
517 : {
518 0 : if (dev_priv->fbc.no_fbc_reason == reason)
519 : return;
520 :
521 0 : dev_priv->fbc.no_fbc_reason = reason;
522 0 : DRM_DEBUG_KMS("Disabling FBC: %s\n", intel_no_fbc_reason_str(reason));
523 0 : }
524 :
525 0 : static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
526 : {
527 : struct drm_crtc *crtc = NULL, *tmp_crtc;
528 : enum pipe pipe;
529 : bool pipe_a_only = false;
530 :
531 0 : if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
532 0 : pipe_a_only = true;
533 :
534 0 : for_each_pipe(dev_priv, pipe) {
535 0 : tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
536 :
537 0 : if (intel_crtc_active(tmp_crtc) &&
538 0 : to_intel_plane_state(tmp_crtc->primary->state)->visible)
539 0 : crtc = tmp_crtc;
540 :
541 0 : if (pipe_a_only)
542 : break;
543 : }
544 :
545 0 : if (!crtc || crtc->primary->fb == NULL)
546 0 : return NULL;
547 :
548 0 : return crtc;
549 0 : }
550 :
551 0 : static bool multiple_pipes_ok(struct drm_i915_private *dev_priv)
552 : {
553 : enum pipe pipe;
554 : int n_pipes = 0;
555 : struct drm_crtc *crtc;
556 :
557 0 : if (INTEL_INFO(dev_priv)->gen > 4)
558 0 : return true;
559 :
560 0 : for_each_pipe(dev_priv, pipe) {
561 0 : crtc = dev_priv->pipe_to_crtc_mapping[pipe];
562 :
563 0 : if (intel_crtc_active(crtc) &&
564 0 : to_intel_plane_state(crtc->primary->state)->visible)
565 0 : n_pipes++;
566 : }
567 :
568 0 : return (n_pipes < 2);
569 0 : }
570 :
571 0 : static int find_compression_threshold(struct drm_i915_private *dev_priv,
572 : struct drm_mm_node *node,
573 : int size,
574 : int fb_cpp)
575 : {
576 : int compression_threshold = 1;
577 : int ret;
578 : u64 end;
579 :
580 : /* The FBC hardware for BDW/SKL doesn't have access to the stolen
581 : * reserved range size, so it always assumes the maximum (8mb) is used.
582 : * If we enable FBC using a CFB on that memory range we'll get FIFO
583 : * underruns, even if that range is not reserved by the BIOS. */
584 0 : if (IS_BROADWELL(dev_priv) ||
585 0 : IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
586 0 : end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024;
587 : else
588 0 : end = dev_priv->gtt.stolen_usable_size;
589 :
590 : /* HACK: This code depends on what we will do in *_enable_fbc. If that
591 : * code changes, this code needs to change as well.
592 : *
593 : * The enable_fbc code will attempt to use one of our 2 compression
594 : * thresholds, therefore, in that case, we only have 1 resort.
595 : */
596 :
597 : /* Try to over-allocate to reduce reallocations and fragmentation. */
598 0 : ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1,
599 : 4096, 0, end);
600 0 : if (ret == 0)
601 0 : return compression_threshold;
602 :
603 : again:
604 : /* HW's ability to limit the CFB is 1:4 */
605 0 : if (compression_threshold > 4 ||
606 0 : (fb_cpp == 2 && compression_threshold == 2))
607 0 : return 0;
608 :
609 0 : ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
610 : 4096, 0, end);
611 0 : if (ret && INTEL_INFO(dev_priv)->gen <= 4) {
612 0 : return 0;
613 0 : } else if (ret) {
614 0 : compression_threshold <<= 1;
615 0 : goto again;
616 : } else {
617 0 : return compression_threshold;
618 : }
619 0 : }
620 :
621 0 : static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, int size,
622 : int fb_cpp)
623 : {
624 : struct drm_mm_node *uninitialized_var(compressed_llb);
625 : int ret;
626 :
627 0 : ret = find_compression_threshold(dev_priv, &dev_priv->fbc.compressed_fb,
628 : size, fb_cpp);
629 0 : if (!ret)
630 : goto err_llb;
631 : else if (ret > 1) {
632 : DRM_INFO("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");
633 :
634 : }
635 :
636 0 : dev_priv->fbc.threshold = ret;
637 :
638 0 : if (INTEL_INFO(dev_priv)->gen >= 5)
639 0 : I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
640 0 : else if (IS_GM45(dev_priv)) {
641 0 : I915_WRITE(DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
642 0 : } else {
643 0 : compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
644 0 : if (!compressed_llb)
645 : goto err_fb;
646 :
647 0 : ret = i915_gem_stolen_insert_node(dev_priv, compressed_llb,
648 : 4096, 4096);
649 0 : if (ret)
650 : goto err_fb;
651 :
652 0 : dev_priv->fbc.compressed_llb = compressed_llb;
653 :
654 0 : I915_WRITE(FBC_CFB_BASE,
655 : dev_priv->mm.stolen_base + dev_priv->fbc.compressed_fb.start);
656 0 : I915_WRITE(FBC_LL_BASE,
657 : dev_priv->mm.stolen_base + compressed_llb->start);
658 : }
659 :
660 0 : dev_priv->fbc.uncompressed_size = size;
661 :
662 : DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
663 : dev_priv->fbc.compressed_fb.size,
664 : dev_priv->fbc.threshold);
665 :
666 0 : return 0;
667 :
668 : err_fb:
669 0 : kfree(compressed_llb);
670 0 : i915_gem_stolen_remove_node(dev_priv, &dev_priv->fbc.compressed_fb);
671 : err_llb:
672 : pr_info_once("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);
673 0 : return -ENOSPC;
674 0 : }
675 :
676 0 : static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
677 : {
678 0 : if (dev_priv->fbc.uncompressed_size == 0)
679 : return;
680 :
681 0 : i915_gem_stolen_remove_node(dev_priv, &dev_priv->fbc.compressed_fb);
682 :
683 0 : if (dev_priv->fbc.compressed_llb) {
684 0 : i915_gem_stolen_remove_node(dev_priv,
685 : dev_priv->fbc.compressed_llb);
686 0 : kfree(dev_priv->fbc.compressed_llb);
687 0 : }
688 :
689 0 : dev_priv->fbc.uncompressed_size = 0;
690 0 : }
691 :
692 0 : void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
693 : {
694 0 : if (!fbc_supported(dev_priv))
695 : return;
696 :
697 0 : mutex_lock(&dev_priv->fbc.lock);
698 0 : __intel_fbc_cleanup_cfb(dev_priv);
699 0 : mutex_unlock(&dev_priv->fbc.lock);
700 0 : }
701 :
702 : /*
703 : * For SKL+, the plane source size used by the hardware is based on the value we
704 : * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value
705 : * we wrote to PIPESRC.
706 : */
707 0 : static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc,
708 : int *width, int *height)
709 : {
710 : struct intel_plane_state *plane_state =
711 0 : to_intel_plane_state(crtc->base.primary->state);
712 : int w, h;
713 :
714 0 : if (intel_rotation_90_or_270(plane_state->base.rotation)) {
715 0 : w = drm_rect_height(&plane_state->src) >> 16;
716 0 : h = drm_rect_width(&plane_state->src) >> 16;
717 0 : } else {
718 0 : w = drm_rect_width(&plane_state->src) >> 16;
719 0 : h = drm_rect_height(&plane_state->src) >> 16;
720 : }
721 :
722 0 : if (width)
723 0 : *width = w;
724 0 : if (height)
725 0 : *height = h;
726 0 : }
727 :
728 0 : static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc)
729 : {
730 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
731 0 : struct drm_framebuffer *fb = crtc->base.primary->fb;
732 0 : int lines;
733 :
734 0 : intel_fbc_get_plane_source_size(crtc, NULL, &lines);
735 0 : if (INTEL_INFO(dev_priv)->gen >= 7)
736 0 : lines = min(lines, 2048);
737 :
738 0 : return lines * fb->pitches[0];
739 0 : }
740 :
741 0 : static int intel_fbc_setup_cfb(struct intel_crtc *crtc)
742 : {
743 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
744 0 : struct drm_framebuffer *fb = crtc->base.primary->fb;
745 : int size, cpp;
746 :
747 0 : size = intel_fbc_calculate_cfb_size(crtc);
748 0 : cpp = drm_format_plane_cpp(fb->pixel_format, 0);
749 :
750 0 : if (size <= dev_priv->fbc.uncompressed_size)
751 0 : return 0;
752 :
753 : /* Release any current block */
754 0 : __intel_fbc_cleanup_cfb(dev_priv);
755 :
756 0 : return intel_fbc_alloc_cfb(dev_priv, size, cpp);
757 0 : }
758 :
759 0 : static bool stride_is_valid(struct drm_i915_private *dev_priv,
760 : unsigned int stride)
761 : {
762 : /* These should have been caught earlier. */
763 0 : WARN_ON(stride < 512);
764 0 : WARN_ON((stride & (64 - 1)) != 0);
765 :
766 : /* Below are the additional FBC restrictions. */
767 :
768 0 : if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv))
769 0 : return stride == 4096 || stride == 8192;
770 :
771 0 : if (IS_GEN4(dev_priv) && !IS_G4X(dev_priv) && stride < 2048)
772 0 : return false;
773 :
774 0 : if (stride > 16384)
775 0 : return false;
776 :
777 0 : return true;
778 0 : }
779 :
780 0 : static bool pixel_format_is_valid(struct drm_framebuffer *fb)
781 : {
782 0 : struct drm_device *dev = fb->dev;
783 0 : struct drm_i915_private *dev_priv = dev->dev_private;
784 :
785 0 : switch (fb->pixel_format) {
786 : case DRM_FORMAT_XRGB8888:
787 : case DRM_FORMAT_XBGR8888:
788 0 : return true;
789 : case DRM_FORMAT_XRGB1555:
790 : case DRM_FORMAT_RGB565:
791 : /* 16bpp not supported on gen2 */
792 0 : if (IS_GEN2(dev))
793 0 : return false;
794 : /* WaFbcOnly1to1Ratio:ctg */
795 0 : if (IS_G4X(dev_priv))
796 0 : return false;
797 0 : return true;
798 : default:
799 0 : return false;
800 : }
801 0 : }
802 :
803 : /*
804 : * For some reason, the hardware tracking starts looking at whatever we
805 : * programmed as the display plane base address register. It does not look at
806 : * the X and Y offset registers. That's why we look at the crtc->adjusted{x,y}
807 : * variables instead of just looking at the pipe/plane size.
808 : */
809 0 : static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
810 : {
811 0 : struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
812 0 : unsigned int effective_w, effective_h, max_w, max_h;
813 :
814 0 : if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
815 : max_w = 4096;
816 : max_h = 4096;
817 0 : } else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
818 : max_w = 4096;
819 : max_h = 2048;
820 0 : } else {
821 : max_w = 2048;
822 : max_h = 1536;
823 : }
824 :
825 0 : intel_fbc_get_plane_source_size(crtc, &effective_w, &effective_h);
826 0 : effective_w += crtc->adjusted_x;
827 0 : effective_h += crtc->adjusted_y;
828 :
829 0 : return effective_w <= max_w && effective_h <= max_h;
830 0 : }
831 :
832 : /**
833 : * __intel_fbc_update - enable/disable FBC as needed, unlocked
834 : * @dev_priv: i915 device instance
835 : *
836 : * Set up the framebuffer compression hardware at mode set time. We
837 : * enable it if possible:
838 : * - plane A only (on pre-965)
839 : * - no pixel mulitply/line duplication
840 : * - no alpha buffer discard
841 : * - no dual wide
842 : * - framebuffer <= max_hdisplay in width, max_vdisplay in height
843 : *
844 : * We can't assume that any compression will take place (worst case),
845 : * so the compressed buffer has to be the same size as the uncompressed
846 : * one. It also must reside (along with the line length buffer) in
847 : * stolen memory.
848 : *
849 : * We need to enable/disable FBC on a global basis.
850 : */
851 0 : static void __intel_fbc_update(struct drm_i915_private *dev_priv)
852 : {
853 : struct drm_crtc *crtc = NULL;
854 : struct intel_crtc *intel_crtc;
855 : struct drm_framebuffer *fb;
856 : struct drm_i915_gem_object *obj;
857 : const struct drm_display_mode *adjusted_mode;
858 :
859 0 : WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
860 :
861 : /* disable framebuffer compression in vGPU */
862 0 : if (intel_vgpu_active(dev_priv->dev))
863 0 : i915.enable_fbc = 0;
864 :
865 0 : if (i915.enable_fbc < 0) {
866 0 : set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT);
867 0 : goto out_disable;
868 : }
869 :
870 0 : if (!i915.enable_fbc) {
871 0 : set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM);
872 0 : goto out_disable;
873 : }
874 :
875 : /*
876 : * If FBC is already on, we just have to verify that we can
877 : * keep it that way...
878 : * Need to disable if:
879 : * - more than one pipe is active
880 : * - changing FBC params (stride, fence, mode)
881 : * - new fb is too large to fit in compressed buffer
882 : * - going to an unsupported config (interlace, pixel multiply, etc.)
883 : */
884 0 : crtc = intel_fbc_find_crtc(dev_priv);
885 0 : if (!crtc) {
886 0 : set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT);
887 0 : goto out_disable;
888 : }
889 :
890 0 : if (!multiple_pipes_ok(dev_priv)) {
891 0 : set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES);
892 0 : goto out_disable;
893 : }
894 :
895 0 : intel_crtc = to_intel_crtc(crtc);
896 0 : fb = crtc->primary->fb;
897 0 : obj = intel_fb_obj(fb);
898 0 : adjusted_mode = &intel_crtc->config->base.adjusted_mode;
899 :
900 0 : if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
901 0 : (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
902 0 : set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE);
903 0 : goto out_disable;
904 : }
905 :
906 0 : if (!intel_fbc_hw_tracking_covers_screen(intel_crtc)) {
907 0 : set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE);
908 0 : goto out_disable;
909 : }
910 :
911 0 : if ((INTEL_INFO(dev_priv)->gen < 4 || HAS_DDI(dev_priv)) &&
912 0 : intel_crtc->plane != PLANE_A) {
913 0 : set_no_fbc_reason(dev_priv, FBC_BAD_PLANE);
914 0 : goto out_disable;
915 : }
916 :
917 : /* The use of a CPU fence is mandatory in order to detect writes
918 : * by the CPU to the scanout and trigger updates to the FBC.
919 : */
920 0 : if (obj->tiling_mode != I915_TILING_X ||
921 0 : obj->fence_reg == I915_FENCE_REG_NONE) {
922 0 : set_no_fbc_reason(dev_priv, FBC_NOT_TILED);
923 0 : goto out_disable;
924 : }
925 0 : if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
926 0 : crtc->primary->state->rotation != BIT(DRM_ROTATE_0)) {
927 0 : set_no_fbc_reason(dev_priv, FBC_ROTATION);
928 0 : goto out_disable;
929 : }
930 :
931 0 : if (!stride_is_valid(dev_priv, fb->pitches[0])) {
932 0 : set_no_fbc_reason(dev_priv, FBC_BAD_STRIDE);
933 0 : goto out_disable;
934 : }
935 :
936 0 : if (!pixel_format_is_valid(fb)) {
937 0 : set_no_fbc_reason(dev_priv, FBC_PIXEL_FORMAT);
938 0 : goto out_disable;
939 : }
940 :
941 : /* If the kernel debugger is active, always disable compression */
942 0 : if (in_dbg_master()) {
943 0 : set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER);
944 0 : goto out_disable;
945 : }
946 :
947 : /* WaFbcExceedCdClockThreshold:hsw,bdw */
948 0 : if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
949 0 : ilk_pipe_pixel_rate(intel_crtc->config) >=
950 0 : dev_priv->cdclk_freq * 95 / 100) {
951 0 : set_no_fbc_reason(dev_priv, FBC_PIXEL_RATE);
952 0 : goto out_disable;
953 : }
954 :
955 0 : if (intel_fbc_setup_cfb(intel_crtc)) {
956 0 : set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL);
957 0 : goto out_disable;
958 : }
959 :
960 : /* If the scanout has not changed, don't modify the FBC settings.
961 : * Note that we make the fundamental assumption that the fb->obj
962 : * cannot be unpinned (and have its GTT offset and fence revoked)
963 : * without first being decoupled from the scanout and FBC disabled.
964 : */
965 0 : if (dev_priv->fbc.crtc == intel_crtc &&
966 0 : dev_priv->fbc.fb_id == fb->base.id &&
967 0 : dev_priv->fbc.y == crtc->y)
968 0 : return;
969 :
970 0 : if (intel_fbc_enabled(dev_priv)) {
971 : /* We update FBC along two paths, after changing fb/crtc
972 : * configuration (modeswitching) and after page-flipping
973 : * finishes. For the latter, we know that not only did
974 : * we disable the FBC at the start of the page-flip
975 : * sequence, but also more than one vblank has passed.
976 : *
977 : * For the former case of modeswitching, it is possible
978 : * to switch between two FBC valid configurations
979 : * instantaneously so we do need to disable the FBC
980 : * before we can modify its control registers. We also
981 : * have to wait for the next vblank for that to take
982 : * effect. However, since we delay enabling FBC we can
983 : * assume that a vblank has passed since disabling and
984 : * that we can safely alter the registers in the deferred
985 : * callback.
986 : *
987 : * In the scenario that we go from a valid to invalid
988 : * and then back to valid FBC configuration we have
989 : * no strict enforcement that a vblank occurred since
990 : * disabling the FBC. However, along all current pipe
991 : * disabling paths we do need to wait for a vblank at
992 : * some point. And we wait before enabling FBC anyway.
993 : */
994 : DRM_DEBUG_KMS("disabling active FBC for update\n");
995 0 : __intel_fbc_disable(dev_priv);
996 0 : }
997 :
998 0 : intel_fbc_schedule_enable(intel_crtc);
999 0 : dev_priv->fbc.no_fbc_reason = FBC_OK;
1000 0 : return;
1001 :
1002 : out_disable:
1003 : /* Multiple disables should be harmless */
1004 0 : if (intel_fbc_enabled(dev_priv)) {
1005 : DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
1006 0 : __intel_fbc_disable(dev_priv);
1007 0 : }
1008 0 : __intel_fbc_cleanup_cfb(dev_priv);
1009 0 : }
1010 :
1011 : /*
1012 : * intel_fbc_update - enable/disable FBC as needed
1013 : * @dev_priv: i915 device instance
1014 : *
1015 : * This function reevaluates the overall state and enables or disables FBC.
1016 : */
1017 0 : void intel_fbc_update(struct drm_i915_private *dev_priv)
1018 : {
1019 0 : if (!fbc_supported(dev_priv))
1020 : return;
1021 :
1022 0 : mutex_lock(&dev_priv->fbc.lock);
1023 0 : __intel_fbc_update(dev_priv);
1024 0 : mutex_unlock(&dev_priv->fbc.lock);
1025 0 : }
1026 :
1027 0 : void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
1028 : unsigned int frontbuffer_bits,
1029 : enum fb_op_origin origin)
1030 : {
1031 : unsigned int fbc_bits;
1032 :
1033 0 : if (!fbc_supported(dev_priv))
1034 0 : return;
1035 :
1036 0 : if (origin == ORIGIN_GTT)
1037 0 : return;
1038 :
1039 0 : mutex_lock(&dev_priv->fbc.lock);
1040 :
1041 0 : if (dev_priv->fbc.enabled)
1042 0 : fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
1043 0 : else if (dev_priv->fbc.fbc_work)
1044 0 : fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
1045 : dev_priv->fbc.fbc_work->crtc->pipe);
1046 : else
1047 0 : fbc_bits = dev_priv->fbc.possible_framebuffer_bits;
1048 :
1049 0 : dev_priv->fbc.busy_bits |= (fbc_bits & frontbuffer_bits);
1050 :
1051 0 : if (dev_priv->fbc.busy_bits)
1052 0 : __intel_fbc_disable(dev_priv);
1053 :
1054 0 : mutex_unlock(&dev_priv->fbc.lock);
1055 0 : }
1056 :
1057 0 : void intel_fbc_flush(struct drm_i915_private *dev_priv,
1058 : unsigned int frontbuffer_bits, enum fb_op_origin origin)
1059 : {
1060 0 : if (!fbc_supported(dev_priv))
1061 : return;
1062 :
1063 0 : if (origin == ORIGIN_GTT)
1064 : return;
1065 :
1066 0 : mutex_lock(&dev_priv->fbc.lock);
1067 :
1068 0 : dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
1069 :
1070 0 : if (!dev_priv->fbc.busy_bits) {
1071 0 : __intel_fbc_disable(dev_priv);
1072 0 : __intel_fbc_update(dev_priv);
1073 0 : }
1074 :
1075 0 : mutex_unlock(&dev_priv->fbc.lock);
1076 0 : }
1077 :
1078 : /**
1079 : * intel_fbc_init - Initialize FBC
1080 : * @dev_priv: the i915 device
1081 : *
1082 : * This function might be called during PM init process.
1083 : */
1084 0 : void intel_fbc_init(struct drm_i915_private *dev_priv)
1085 : {
1086 : enum pipe pipe;
1087 :
1088 0 : rw_init(&dev_priv->fbc.lock, "fbclk");
1089 :
1090 0 : if (!HAS_FBC(dev_priv)) {
1091 0 : dev_priv->fbc.enabled = false;
1092 0 : dev_priv->fbc.no_fbc_reason = FBC_UNSUPPORTED;
1093 0 : return;
1094 : }
1095 :
1096 0 : for_each_pipe(dev_priv, pipe) {
1097 0 : dev_priv->fbc.possible_framebuffer_bits |=
1098 0 : INTEL_FRONTBUFFER_PRIMARY(pipe);
1099 :
1100 0 : if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
1101 : break;
1102 : }
1103 :
1104 0 : if (INTEL_INFO(dev_priv)->gen >= 7) {
1105 0 : dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
1106 0 : dev_priv->fbc.enable_fbc = gen7_fbc_enable;
1107 0 : dev_priv->fbc.disable_fbc = ilk_fbc_disable;
1108 0 : } else if (INTEL_INFO(dev_priv)->gen >= 5) {
1109 0 : dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
1110 0 : dev_priv->fbc.enable_fbc = ilk_fbc_enable;
1111 0 : dev_priv->fbc.disable_fbc = ilk_fbc_disable;
1112 0 : } else if (IS_GM45(dev_priv)) {
1113 0 : dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
1114 0 : dev_priv->fbc.enable_fbc = g4x_fbc_enable;
1115 0 : dev_priv->fbc.disable_fbc = g4x_fbc_disable;
1116 0 : } else {
1117 0 : dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled;
1118 0 : dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
1119 0 : dev_priv->fbc.disable_fbc = i8xx_fbc_disable;
1120 :
1121 : /* This value was pulled out of someone's hat */
1122 0 : I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
1123 : }
1124 :
1125 0 : dev_priv->fbc.enabled = dev_priv->fbc.fbc_enabled(dev_priv);
1126 0 : }
|