2 * Copyright © 2011 Intel Corporation
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:
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
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * Jesse Barnes <jbarnes@virtuousgeek.org>
26 * New plane/sprite handling.
28 * The older chips had a separate interface for programming plane related
29 * registers; newer ones are much simpler and we can use the new DRM plane
33 #include <drm/drm_crtc.h>
34 #include <drm/drm_fourcc.h>
35 #include <drm/drm_rect.h>
36 #include "intel_drv.h"
37 #include <drm/i915_drm.h>
41 vlv_update_plane(struct drm_plane
*dplane
, struct drm_crtc
*crtc
,
42 struct drm_framebuffer
*fb
,
43 struct drm_i915_gem_object
*obj
, int crtc_x
, int crtc_y
,
44 unsigned int crtc_w
, unsigned int crtc_h
,
45 uint32_t x
, uint32_t y
,
46 uint32_t src_w
, uint32_t src_h
)
48 struct drm_device
*dev
= dplane
->dev
;
49 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
50 struct intel_plane
*intel_plane
= to_intel_plane(dplane
);
51 int pipe
= intel_plane
->pipe
;
52 int plane
= intel_plane
->plane
;
54 unsigned long sprsurf_offset
, linear_offset
;
55 int pixel_size
= drm_format_plane_cpp(fb
->pixel_format
, 0);
57 sprctl
= I915_READ(SPCNTR(pipe
, plane
));
59 /* Mask out pixel format bits in case we change it */
60 sprctl
&= ~SP_PIXFORMAT_MASK
;
61 sprctl
&= ~SP_YUV_BYTE_ORDER_MASK
;
64 switch (fb
->pixel_format
) {
66 sprctl
|= SP_FORMAT_YUV422
| SP_YUV_ORDER_YUYV
;
69 sprctl
|= SP_FORMAT_YUV422
| SP_YUV_ORDER_YVYU
;
72 sprctl
|= SP_FORMAT_YUV422
| SP_YUV_ORDER_UYVY
;
75 sprctl
|= SP_FORMAT_YUV422
| SP_YUV_ORDER_VYUY
;
77 case DRM_FORMAT_RGB565
:
78 sprctl
|= SP_FORMAT_BGR565
;
80 case DRM_FORMAT_XRGB8888
:
81 sprctl
|= SP_FORMAT_BGRX8888
;
83 case DRM_FORMAT_ARGB8888
:
84 sprctl
|= SP_FORMAT_BGRA8888
;
86 case DRM_FORMAT_XBGR2101010
:
87 sprctl
|= SP_FORMAT_RGBX1010102
;
89 case DRM_FORMAT_ABGR2101010
:
90 sprctl
|= SP_FORMAT_RGBA1010102
;
92 case DRM_FORMAT_XBGR8888
:
93 sprctl
|= SP_FORMAT_RGBX8888
;
95 case DRM_FORMAT_ABGR8888
:
96 sprctl
|= SP_FORMAT_RGBA8888
;
100 * If we get here one of the upper layers failed to filter
101 * out the unsupported plane formats
108 * Enable gamma to match primary/cursor plane behaviour.
109 * FIXME should be user controllable via propertiesa.
111 sprctl
|= SP_GAMMA_ENABLE
;
113 if (obj
->tiling_mode
!= I915_TILING_NONE
)
118 intel_update_sprite_watermarks(dplane
, crtc
, src_w
, pixel_size
, true,
119 src_w
!= crtc_w
|| src_h
!= crtc_h
);
121 /* Sizes are 0 based */
127 I915_WRITE(SPSTRIDE(pipe
, plane
), fb
->pitches
[0]);
128 I915_WRITE(SPPOS(pipe
, plane
), (crtc_y
<< 16) | crtc_x
);
130 linear_offset
= y
* fb
->pitches
[0] + x
* pixel_size
;
131 sprsurf_offset
= intel_gen4_compute_page_offset(&x
, &y
,
135 linear_offset
-= sprsurf_offset
;
137 if (obj
->tiling_mode
!= I915_TILING_NONE
)
138 I915_WRITE(SPTILEOFF(pipe
, plane
), (y
<< 16) | x
);
140 I915_WRITE(SPLINOFF(pipe
, plane
), linear_offset
);
142 I915_WRITE(SPSIZE(pipe
, plane
), (crtc_h
<< 16) | crtc_w
);
143 I915_WRITE(SPCNTR(pipe
, plane
), sprctl
);
144 I915_MODIFY_DISPBASE(SPSURF(pipe
, plane
), i915_gem_obj_ggtt_offset(obj
) +
146 POSTING_READ(SPSURF(pipe
, plane
));
150 vlv_disable_plane(struct drm_plane
*dplane
, struct drm_crtc
*crtc
)
152 struct drm_device
*dev
= dplane
->dev
;
153 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
154 struct intel_plane
*intel_plane
= to_intel_plane(dplane
);
155 int pipe
= intel_plane
->pipe
;
156 int plane
= intel_plane
->plane
;
158 I915_WRITE(SPCNTR(pipe
, plane
), I915_READ(SPCNTR(pipe
, plane
)) &
160 /* Activate double buffered register update */
161 I915_MODIFY_DISPBASE(SPSURF(pipe
, plane
), 0);
162 POSTING_READ(SPSURF(pipe
, plane
));
164 intel_update_sprite_watermarks(dplane
, crtc
, 0, 0, false, false);
168 vlv_update_colorkey(struct drm_plane
*dplane
,
169 struct drm_intel_sprite_colorkey
*key
)
171 struct drm_device
*dev
= dplane
->dev
;
172 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
173 struct intel_plane
*intel_plane
= to_intel_plane(dplane
);
174 int pipe
= intel_plane
->pipe
;
175 int plane
= intel_plane
->plane
;
178 if (key
->flags
& I915_SET_COLORKEY_DESTINATION
)
181 I915_WRITE(SPKEYMINVAL(pipe
, plane
), key
->min_value
);
182 I915_WRITE(SPKEYMAXVAL(pipe
, plane
), key
->max_value
);
183 I915_WRITE(SPKEYMSK(pipe
, plane
), key
->channel_mask
);
185 sprctl
= I915_READ(SPCNTR(pipe
, plane
));
186 sprctl
&= ~SP_SOURCE_KEY
;
187 if (key
->flags
& I915_SET_COLORKEY_SOURCE
)
188 sprctl
|= SP_SOURCE_KEY
;
189 I915_WRITE(SPCNTR(pipe
, plane
), sprctl
);
191 POSTING_READ(SPKEYMSK(pipe
, plane
));
197 vlv_get_colorkey(struct drm_plane
*dplane
,
198 struct drm_intel_sprite_colorkey
*key
)
200 struct drm_device
*dev
= dplane
->dev
;
201 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
202 struct intel_plane
*intel_plane
= to_intel_plane(dplane
);
203 int pipe
= intel_plane
->pipe
;
204 int plane
= intel_plane
->plane
;
207 key
->min_value
= I915_READ(SPKEYMINVAL(pipe
, plane
));
208 key
->max_value
= I915_READ(SPKEYMAXVAL(pipe
, plane
));
209 key
->channel_mask
= I915_READ(SPKEYMSK(pipe
, plane
));
211 sprctl
= I915_READ(SPCNTR(pipe
, plane
));
212 if (sprctl
& SP_SOURCE_KEY
)
213 key
->flags
= I915_SET_COLORKEY_SOURCE
;
215 key
->flags
= I915_SET_COLORKEY_NONE
;
219 ivb_update_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
220 struct drm_framebuffer
*fb
,
221 struct drm_i915_gem_object
*obj
, int crtc_x
, int crtc_y
,
222 unsigned int crtc_w
, unsigned int crtc_h
,
223 uint32_t x
, uint32_t y
,
224 uint32_t src_w
, uint32_t src_h
)
226 struct drm_device
*dev
= plane
->dev
;
227 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
228 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
229 int pipe
= intel_plane
->pipe
;
230 u32 sprctl
, sprscale
= 0;
231 unsigned long sprsurf_offset
, linear_offset
;
232 int pixel_size
= drm_format_plane_cpp(fb
->pixel_format
, 0);
233 bool scaling_was_enabled
= dev_priv
->sprite_scaling_enabled
;
235 sprctl
= I915_READ(SPRCTL(pipe
));
237 /* Mask out pixel format bits in case we change it */
238 sprctl
&= ~SPRITE_PIXFORMAT_MASK
;
239 sprctl
&= ~SPRITE_RGB_ORDER_RGBX
;
240 sprctl
&= ~SPRITE_YUV_BYTE_ORDER_MASK
;
241 sprctl
&= ~SPRITE_TILED
;
243 switch (fb
->pixel_format
) {
244 case DRM_FORMAT_XBGR8888
:
245 sprctl
|= SPRITE_FORMAT_RGBX888
| SPRITE_RGB_ORDER_RGBX
;
247 case DRM_FORMAT_XRGB8888
:
248 sprctl
|= SPRITE_FORMAT_RGBX888
;
250 case DRM_FORMAT_YUYV
:
251 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_YUYV
;
253 case DRM_FORMAT_YVYU
:
254 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_YVYU
;
256 case DRM_FORMAT_UYVY
:
257 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_UYVY
;
259 case DRM_FORMAT_VYUY
:
260 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_VYUY
;
267 * Enable gamma to match primary/cursor plane behaviour.
268 * FIXME should be user controllable via propertiesa.
270 sprctl
|= SPRITE_GAMMA_ENABLE
;
272 if (obj
->tiling_mode
!= I915_TILING_NONE
)
273 sprctl
|= SPRITE_TILED
;
275 if (IS_HASWELL(dev
) || IS_BROADWELL(dev
))
276 sprctl
&= ~SPRITE_TRICKLE_FEED_DISABLE
;
278 sprctl
|= SPRITE_TRICKLE_FEED_DISABLE
;
280 sprctl
|= SPRITE_ENABLE
;
282 if (IS_HASWELL(dev
) || IS_BROADWELL(dev
))
283 sprctl
|= SPRITE_PIPE_CSC_ENABLE
;
285 intel_update_sprite_watermarks(plane
, crtc
, src_w
, pixel_size
, true,
286 src_w
!= crtc_w
|| src_h
!= crtc_h
);
288 /* Sizes are 0 based */
295 * IVB workaround: must disable low power watermarks for at least
296 * one frame before enabling scaling. LP watermarks can be re-enabled
297 * when scaling is disabled.
299 if (crtc_w
!= src_w
|| crtc_h
!= src_h
) {
300 dev_priv
->sprite_scaling_enabled
|= 1 << pipe
;
302 if (!scaling_was_enabled
) {
303 intel_update_watermarks(crtc
);
304 intel_wait_for_vblank(dev
, pipe
);
306 sprscale
= SPRITE_SCALE_ENABLE
| (src_w
<< 16) | src_h
;
308 dev_priv
->sprite_scaling_enabled
&= ~(1 << pipe
);
310 I915_WRITE(SPRSTRIDE(pipe
), fb
->pitches
[0]);
311 I915_WRITE(SPRPOS(pipe
), (crtc_y
<< 16) | crtc_x
);
313 linear_offset
= y
* fb
->pitches
[0] + x
* pixel_size
;
315 intel_gen4_compute_page_offset(&x
, &y
, obj
->tiling_mode
,
316 pixel_size
, fb
->pitches
[0]);
317 linear_offset
-= sprsurf_offset
;
319 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
321 if (IS_HASWELL(dev
) || IS_BROADWELL(dev
))
322 I915_WRITE(SPROFFSET(pipe
), (y
<< 16) | x
);
323 else if (obj
->tiling_mode
!= I915_TILING_NONE
)
324 I915_WRITE(SPRTILEOFF(pipe
), (y
<< 16) | x
);
326 I915_WRITE(SPRLINOFF(pipe
), linear_offset
);
328 I915_WRITE(SPRSIZE(pipe
), (crtc_h
<< 16) | crtc_w
);
329 if (intel_plane
->can_scale
)
330 I915_WRITE(SPRSCALE(pipe
), sprscale
);
331 I915_WRITE(SPRCTL(pipe
), sprctl
);
332 I915_MODIFY_DISPBASE(SPRSURF(pipe
),
333 i915_gem_obj_ggtt_offset(obj
) + sprsurf_offset
);
334 POSTING_READ(SPRSURF(pipe
));
336 /* potentially re-enable LP watermarks */
337 if (scaling_was_enabled
&& !dev_priv
->sprite_scaling_enabled
)
338 intel_update_watermarks(crtc
);
342 ivb_disable_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
)
344 struct drm_device
*dev
= plane
->dev
;
345 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
346 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
347 int pipe
= intel_plane
->pipe
;
348 bool scaling_was_enabled
= dev_priv
->sprite_scaling_enabled
;
350 I915_WRITE(SPRCTL(pipe
), I915_READ(SPRCTL(pipe
)) & ~SPRITE_ENABLE
);
351 /* Can't leave the scaler enabled... */
352 if (intel_plane
->can_scale
)
353 I915_WRITE(SPRSCALE(pipe
), 0);
354 /* Activate double buffered register update */
355 I915_MODIFY_DISPBASE(SPRSURF(pipe
), 0);
356 POSTING_READ(SPRSURF(pipe
));
358 dev_priv
->sprite_scaling_enabled
&= ~(1 << pipe
);
360 intel_update_sprite_watermarks(plane
, crtc
, 0, 0, false, false);
362 /* potentially re-enable LP watermarks */
363 if (scaling_was_enabled
&& !dev_priv
->sprite_scaling_enabled
)
364 intel_update_watermarks(crtc
);
368 ivb_update_colorkey(struct drm_plane
*plane
,
369 struct drm_intel_sprite_colorkey
*key
)
371 struct drm_device
*dev
= plane
->dev
;
372 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
373 struct intel_plane
*intel_plane
;
377 intel_plane
= to_intel_plane(plane
);
379 I915_WRITE(SPRKEYVAL(intel_plane
->pipe
), key
->min_value
);
380 I915_WRITE(SPRKEYMAX(intel_plane
->pipe
), key
->max_value
);
381 I915_WRITE(SPRKEYMSK(intel_plane
->pipe
), key
->channel_mask
);
383 sprctl
= I915_READ(SPRCTL(intel_plane
->pipe
));
384 sprctl
&= ~(SPRITE_SOURCE_KEY
| SPRITE_DEST_KEY
);
385 if (key
->flags
& I915_SET_COLORKEY_DESTINATION
)
386 sprctl
|= SPRITE_DEST_KEY
;
387 else if (key
->flags
& I915_SET_COLORKEY_SOURCE
)
388 sprctl
|= SPRITE_SOURCE_KEY
;
389 I915_WRITE(SPRCTL(intel_plane
->pipe
), sprctl
);
391 POSTING_READ(SPRKEYMSK(intel_plane
->pipe
));
397 ivb_get_colorkey(struct drm_plane
*plane
, struct drm_intel_sprite_colorkey
*key
)
399 struct drm_device
*dev
= plane
->dev
;
400 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
401 struct intel_plane
*intel_plane
;
404 intel_plane
= to_intel_plane(plane
);
406 key
->min_value
= I915_READ(SPRKEYVAL(intel_plane
->pipe
));
407 key
->max_value
= I915_READ(SPRKEYMAX(intel_plane
->pipe
));
408 key
->channel_mask
= I915_READ(SPRKEYMSK(intel_plane
->pipe
));
411 sprctl
= I915_READ(SPRCTL(intel_plane
->pipe
));
413 if (sprctl
& SPRITE_DEST_KEY
)
414 key
->flags
= I915_SET_COLORKEY_DESTINATION
;
415 else if (sprctl
& SPRITE_SOURCE_KEY
)
416 key
->flags
= I915_SET_COLORKEY_SOURCE
;
418 key
->flags
= I915_SET_COLORKEY_NONE
;
422 ilk_update_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
423 struct drm_framebuffer
*fb
,
424 struct drm_i915_gem_object
*obj
, int crtc_x
, int crtc_y
,
425 unsigned int crtc_w
, unsigned int crtc_h
,
426 uint32_t x
, uint32_t y
,
427 uint32_t src_w
, uint32_t src_h
)
429 struct drm_device
*dev
= plane
->dev
;
430 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
431 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
432 int pipe
= intel_plane
->pipe
;
433 unsigned long dvssurf_offset
, linear_offset
;
434 u32 dvscntr
, dvsscale
;
435 int pixel_size
= drm_format_plane_cpp(fb
->pixel_format
, 0);
437 dvscntr
= I915_READ(DVSCNTR(pipe
));
439 /* Mask out pixel format bits in case we change it */
440 dvscntr
&= ~DVS_PIXFORMAT_MASK
;
441 dvscntr
&= ~DVS_RGB_ORDER_XBGR
;
442 dvscntr
&= ~DVS_YUV_BYTE_ORDER_MASK
;
443 dvscntr
&= ~DVS_TILED
;
445 switch (fb
->pixel_format
) {
446 case DRM_FORMAT_XBGR8888
:
447 dvscntr
|= DVS_FORMAT_RGBX888
| DVS_RGB_ORDER_XBGR
;
449 case DRM_FORMAT_XRGB8888
:
450 dvscntr
|= DVS_FORMAT_RGBX888
;
452 case DRM_FORMAT_YUYV
:
453 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_YUYV
;
455 case DRM_FORMAT_YVYU
:
456 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_YVYU
;
458 case DRM_FORMAT_UYVY
:
459 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_UYVY
;
461 case DRM_FORMAT_VYUY
:
462 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_VYUY
;
469 * Enable gamma to match primary/cursor plane behaviour.
470 * FIXME should be user controllable via propertiesa.
472 dvscntr
|= DVS_GAMMA_ENABLE
;
474 if (obj
->tiling_mode
!= I915_TILING_NONE
)
475 dvscntr
|= DVS_TILED
;
478 dvscntr
|= DVS_TRICKLE_FEED_DISABLE
; /* must disable */
479 dvscntr
|= DVS_ENABLE
;
481 intel_update_sprite_watermarks(plane
, crtc
, src_w
, pixel_size
, true,
482 src_w
!= crtc_w
|| src_h
!= crtc_h
);
484 /* Sizes are 0 based */
491 if (IS_GEN5(dev
) || crtc_w
!= src_w
|| crtc_h
!= src_h
)
492 dvsscale
= DVS_SCALE_ENABLE
| (src_w
<< 16) | src_h
;
494 I915_WRITE(DVSSTRIDE(pipe
), fb
->pitches
[0]);
495 I915_WRITE(DVSPOS(pipe
), (crtc_y
<< 16) | crtc_x
);
497 linear_offset
= y
* fb
->pitches
[0] + x
* pixel_size
;
499 intel_gen4_compute_page_offset(&x
, &y
, obj
->tiling_mode
,
500 pixel_size
, fb
->pitches
[0]);
501 linear_offset
-= dvssurf_offset
;
503 if (obj
->tiling_mode
!= I915_TILING_NONE
)
504 I915_WRITE(DVSTILEOFF(pipe
), (y
<< 16) | x
);
506 I915_WRITE(DVSLINOFF(pipe
), linear_offset
);
508 I915_WRITE(DVSSIZE(pipe
), (crtc_h
<< 16) | crtc_w
);
509 I915_WRITE(DVSSCALE(pipe
), dvsscale
);
510 I915_WRITE(DVSCNTR(pipe
), dvscntr
);
511 I915_MODIFY_DISPBASE(DVSSURF(pipe
),
512 i915_gem_obj_ggtt_offset(obj
) + dvssurf_offset
);
513 POSTING_READ(DVSSURF(pipe
));
517 ilk_disable_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
)
519 struct drm_device
*dev
= plane
->dev
;
520 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
521 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
522 int pipe
= intel_plane
->pipe
;
524 I915_WRITE(DVSCNTR(pipe
), I915_READ(DVSCNTR(pipe
)) & ~DVS_ENABLE
);
525 /* Disable the scaler */
526 I915_WRITE(DVSSCALE(pipe
), 0);
527 /* Flush double buffered register updates */
528 I915_MODIFY_DISPBASE(DVSSURF(pipe
), 0);
529 POSTING_READ(DVSSURF(pipe
));
531 intel_update_sprite_watermarks(plane
, crtc
, 0, 0, false, false);
535 intel_enable_primary(struct drm_crtc
*crtc
)
537 struct drm_device
*dev
= crtc
->dev
;
538 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
539 struct intel_crtc
*intel_crtc
= to_intel_crtc(crtc
);
540 int reg
= DSPCNTR(intel_crtc
->plane
);
542 if (intel_crtc
->primary_enabled
)
545 intel_crtc
->primary_enabled
= true;
547 I915_WRITE(reg
, I915_READ(reg
) | DISPLAY_PLANE_ENABLE
);
548 intel_flush_primary_plane(dev_priv
, intel_crtc
->plane
);
551 * FIXME IPS should be fine as long as one plane is
552 * enabled, but in practice it seems to have problems
553 * when going from primary only to sprite only and vice
556 if (intel_crtc
->config
.ips_enabled
) {
557 intel_wait_for_vblank(dev
, intel_crtc
->pipe
);
558 hsw_enable_ips(intel_crtc
);
561 mutex_lock(&dev
->struct_mutex
);
562 intel_update_fbc(dev
);
563 mutex_unlock(&dev
->struct_mutex
);
567 intel_disable_primary(struct drm_crtc
*crtc
)
569 struct drm_device
*dev
= crtc
->dev
;
570 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
571 struct intel_crtc
*intel_crtc
= to_intel_crtc(crtc
);
572 int reg
= DSPCNTR(intel_crtc
->plane
);
574 if (!intel_crtc
->primary_enabled
)
577 intel_crtc
->primary_enabled
= false;
579 mutex_lock(&dev
->struct_mutex
);
580 if (dev_priv
->fbc
.plane
== intel_crtc
->plane
)
581 intel_disable_fbc(dev
);
582 mutex_unlock(&dev
->struct_mutex
);
585 * FIXME IPS should be fine as long as one plane is
586 * enabled, but in practice it seems to have problems
587 * when going from primary only to sprite only and vice
590 hsw_disable_ips(intel_crtc
);
592 I915_WRITE(reg
, I915_READ(reg
) & ~DISPLAY_PLANE_ENABLE
);
593 intel_flush_primary_plane(dev_priv
, intel_crtc
->plane
);
597 ilk_update_colorkey(struct drm_plane
*plane
,
598 struct drm_intel_sprite_colorkey
*key
)
600 struct drm_device
*dev
= plane
->dev
;
601 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
602 struct intel_plane
*intel_plane
;
606 intel_plane
= to_intel_plane(plane
);
608 I915_WRITE(DVSKEYVAL(intel_plane
->pipe
), key
->min_value
);
609 I915_WRITE(DVSKEYMAX(intel_plane
->pipe
), key
->max_value
);
610 I915_WRITE(DVSKEYMSK(intel_plane
->pipe
), key
->channel_mask
);
612 dvscntr
= I915_READ(DVSCNTR(intel_plane
->pipe
));
613 dvscntr
&= ~(DVS_SOURCE_KEY
| DVS_DEST_KEY
);
614 if (key
->flags
& I915_SET_COLORKEY_DESTINATION
)
615 dvscntr
|= DVS_DEST_KEY
;
616 else if (key
->flags
& I915_SET_COLORKEY_SOURCE
)
617 dvscntr
|= DVS_SOURCE_KEY
;
618 I915_WRITE(DVSCNTR(intel_plane
->pipe
), dvscntr
);
620 POSTING_READ(DVSKEYMSK(intel_plane
->pipe
));
626 ilk_get_colorkey(struct drm_plane
*plane
, struct drm_intel_sprite_colorkey
*key
)
628 struct drm_device
*dev
= plane
->dev
;
629 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
630 struct intel_plane
*intel_plane
;
633 intel_plane
= to_intel_plane(plane
);
635 key
->min_value
= I915_READ(DVSKEYVAL(intel_plane
->pipe
));
636 key
->max_value
= I915_READ(DVSKEYMAX(intel_plane
->pipe
));
637 key
->channel_mask
= I915_READ(DVSKEYMSK(intel_plane
->pipe
));
640 dvscntr
= I915_READ(DVSCNTR(intel_plane
->pipe
));
642 if (dvscntr
& DVS_DEST_KEY
)
643 key
->flags
= I915_SET_COLORKEY_DESTINATION
;
644 else if (dvscntr
& DVS_SOURCE_KEY
)
645 key
->flags
= I915_SET_COLORKEY_SOURCE
;
647 key
->flags
= I915_SET_COLORKEY_NONE
;
651 format_is_yuv(uint32_t format
)
654 case DRM_FORMAT_YUYV
:
655 case DRM_FORMAT_UYVY
:
656 case DRM_FORMAT_VYUY
:
657 case DRM_FORMAT_YVYU
:
665 intel_update_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
666 struct drm_framebuffer
*fb
, int crtc_x
, int crtc_y
,
667 unsigned int crtc_w
, unsigned int crtc_h
,
668 uint32_t src_x
, uint32_t src_y
,
669 uint32_t src_w
, uint32_t src_h
)
671 struct drm_device
*dev
= plane
->dev
;
672 struct intel_crtc
*intel_crtc
= to_intel_crtc(crtc
);
673 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
674 struct intel_framebuffer
*intel_fb
= to_intel_framebuffer(fb
);
675 struct drm_i915_gem_object
*obj
= intel_fb
->obj
;
676 struct drm_i915_gem_object
*old_obj
= intel_plane
->obj
;
678 bool disable_primary
= false;
681 int max_scale
, min_scale
;
682 int pixel_size
= drm_format_plane_cpp(fb
->pixel_format
, 0);
683 struct drm_rect src
= {
684 /* sample coordinates in 16.16 fixed point */
690 struct drm_rect dst
= {
693 .x2
= crtc_x
+ crtc_w
,
695 .y2
= crtc_y
+ crtc_h
,
697 const struct drm_rect clip
= {
698 .x2
= intel_crtc
->active
? intel_crtc
->config
.pipe_src_w
: 0,
699 .y2
= intel_crtc
->active
? intel_crtc
->config
.pipe_src_h
: 0,
703 unsigned int crtc_w
, crtc_h
;
704 uint32_t src_x
, src_y
, src_w
, src_h
;
716 /* Don't modify another pipe's plane */
717 if (intel_plane
->pipe
!= intel_crtc
->pipe
) {
718 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
722 /* FIXME check all gen limits */
723 if (fb
->width
< 3 || fb
->height
< 3 || fb
->pitches
[0] > 16384) {
724 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
728 /* Sprite planes can be linear or x-tiled surfaces */
729 switch (obj
->tiling_mode
) {
730 case I915_TILING_NONE
:
734 DRM_DEBUG_KMS("Unsupported tiling mode\n");
739 * FIXME the following code does a bunch of fuzzy adjustments to the
740 * coordinates and sizes. We probably need some way to decide whether
741 * more strict checking should be done instead.
743 max_scale
= intel_plane
->max_downscale
<< 16;
744 min_scale
= intel_plane
->can_scale
? 1 : (1 << 16);
746 hscale
= drm_rect_calc_hscale_relaxed(&src
, &dst
, min_scale
, max_scale
);
749 vscale
= drm_rect_calc_vscale_relaxed(&src
, &dst
, min_scale
, max_scale
);
752 visible
= drm_rect_clip_scaled(&src
, &dst
, &clip
, hscale
, vscale
);
756 crtc_w
= drm_rect_width(&dst
);
757 crtc_h
= drm_rect_height(&dst
);
760 /* check again in case clipping clamped the results */
761 hscale
= drm_rect_calc_hscale(&src
, &dst
, min_scale
, max_scale
);
763 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
764 drm_rect_debug_print(&src
, true);
765 drm_rect_debug_print(&dst
, false);
770 vscale
= drm_rect_calc_vscale(&src
, &dst
, min_scale
, max_scale
);
772 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
773 drm_rect_debug_print(&src
, true);
774 drm_rect_debug_print(&dst
, false);
779 /* Make the source viewport size an exact multiple of the scaling factors. */
780 drm_rect_adjust_size(&src
,
781 drm_rect_width(&dst
) * hscale
- drm_rect_width(&src
),
782 drm_rect_height(&dst
) * vscale
- drm_rect_height(&src
));
784 /* sanity check to make sure the src viewport wasn't enlarged */
785 WARN_ON(src
.x1
< (int) src_x
||
786 src
.y1
< (int) src_y
||
787 src
.x2
> (int) (src_x
+ src_w
) ||
788 src
.y2
> (int) (src_y
+ src_h
));
791 * Hardware doesn't handle subpixel coordinates.
792 * Adjust to (macro)pixel boundary, but be careful not to
793 * increase the source viewport size, because that could
794 * push the downscaling factor out of bounds.
796 src_x
= src
.x1
>> 16;
797 src_w
= drm_rect_width(&src
) >> 16;
798 src_y
= src
.y1
>> 16;
799 src_h
= drm_rect_height(&src
) >> 16;
801 if (format_is_yuv(fb
->pixel_format
)) {
806 * Must keep src and dst the
807 * same if we can't scale.
809 if (!intel_plane
->can_scale
)
817 /* Check size restrictions when scaling */
818 if (visible
&& (src_w
!= crtc_w
|| src_h
!= crtc_h
)) {
819 unsigned int width_bytes
;
821 WARN_ON(!intel_plane
->can_scale
);
823 /* FIXME interlacing min height is 6 */
825 if (crtc_w
< 3 || crtc_h
< 3)
828 if (src_w
< 3 || src_h
< 3)
831 width_bytes
= ((src_x
* pixel_size
) & 63) + src_w
* pixel_size
;
833 if (src_w
> 2048 || src_h
> 2048 ||
834 width_bytes
> 4096 || fb
->pitches
[0] > 4096) {
835 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
841 dst
.x2
= crtc_x
+ crtc_w
;
843 dst
.y2
= crtc_y
+ crtc_h
;
846 * If the sprite is completely covering the primary plane,
847 * we can disable the primary and save power.
849 disable_primary
= drm_rect_equals(&dst
, &clip
);
850 WARN_ON(disable_primary
&& !visible
&& intel_crtc
->active
);
852 mutex_lock(&dev
->struct_mutex
);
854 /* Note that this will apply the VT-d workaround for scanouts,
855 * which is more restrictive than required for sprites. (The
856 * primary plane requires 256KiB alignment with 64 PTE padding,
857 * the sprite planes only require 128KiB alignment and 32 PTE padding.
859 ret
= intel_pin_and_fence_fb_obj(dev
, obj
, NULL
);
861 mutex_unlock(&dev
->struct_mutex
);
866 intel_plane
->crtc_x
= orig
.crtc_x
;
867 intel_plane
->crtc_y
= orig
.crtc_y
;
868 intel_plane
->crtc_w
= orig
.crtc_w
;
869 intel_plane
->crtc_h
= orig
.crtc_h
;
870 intel_plane
->src_x
= orig
.src_x
;
871 intel_plane
->src_y
= orig
.src_y
;
872 intel_plane
->src_w
= orig
.src_w
;
873 intel_plane
->src_h
= orig
.src_h
;
874 intel_plane
->obj
= obj
;
876 if (intel_crtc
->active
) {
878 * Be sure to re-enable the primary before the sprite is no longer
881 if (!disable_primary
)
882 intel_enable_primary(crtc
);
885 intel_plane
->update_plane(plane
, crtc
, fb
, obj
,
886 crtc_x
, crtc_y
, crtc_w
, crtc_h
,
887 src_x
, src_y
, src_w
, src_h
);
889 intel_plane
->disable_plane(plane
, crtc
);
892 intel_disable_primary(crtc
);
895 /* Unpin old obj after new one is active to avoid ugliness */
898 * It's fairly common to simply update the position of
899 * an existing object. In that case, we don't need to
900 * wait for vblank to avoid ugliness, we only need to
901 * do the pin & ref bookkeeping.
903 if (old_obj
!= obj
&& intel_crtc
->active
)
904 intel_wait_for_vblank(dev
, intel_crtc
->pipe
);
906 mutex_lock(&dev
->struct_mutex
);
907 intel_unpin_fb_obj(old_obj
);
908 mutex_unlock(&dev
->struct_mutex
);
915 intel_disable_plane(struct drm_plane
*plane
)
917 struct drm_device
*dev
= plane
->dev
;
918 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
919 struct intel_crtc
*intel_crtc
;
924 if (WARN_ON(!plane
->crtc
))
927 intel_crtc
= to_intel_crtc(plane
->crtc
);
929 if (intel_crtc
->active
) {
930 intel_enable_primary(plane
->crtc
);
931 intel_plane
->disable_plane(plane
, plane
->crtc
);
934 if (intel_plane
->obj
) {
935 if (intel_crtc
->active
)
936 intel_wait_for_vblank(dev
, intel_plane
->pipe
);
938 mutex_lock(&dev
->struct_mutex
);
939 intel_unpin_fb_obj(intel_plane
->obj
);
940 mutex_unlock(&dev
->struct_mutex
);
942 intel_plane
->obj
= NULL
;
948 static void intel_destroy_plane(struct drm_plane
*plane
)
950 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
951 intel_disable_plane(plane
);
952 drm_plane_cleanup(plane
);
956 int intel_sprite_set_colorkey(struct drm_device
*dev
, void *data
,
957 struct drm_file
*file_priv
)
959 struct drm_intel_sprite_colorkey
*set
= data
;
960 struct drm_mode_object
*obj
;
961 struct drm_plane
*plane
;
962 struct intel_plane
*intel_plane
;
965 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
968 /* Make sure we don't try to enable both src & dest simultaneously */
969 if ((set
->flags
& (I915_SET_COLORKEY_DESTINATION
| I915_SET_COLORKEY_SOURCE
)) == (I915_SET_COLORKEY_DESTINATION
| I915_SET_COLORKEY_SOURCE
))
972 drm_modeset_lock_all(dev
);
974 obj
= drm_mode_object_find(dev
, set
->plane_id
, DRM_MODE_OBJECT_PLANE
);
980 plane
= obj_to_plane(obj
);
981 intel_plane
= to_intel_plane(plane
);
982 ret
= intel_plane
->update_colorkey(plane
, set
);
985 drm_modeset_unlock_all(dev
);
989 int intel_sprite_get_colorkey(struct drm_device
*dev
, void *data
,
990 struct drm_file
*file_priv
)
992 struct drm_intel_sprite_colorkey
*get
= data
;
993 struct drm_mode_object
*obj
;
994 struct drm_plane
*plane
;
995 struct intel_plane
*intel_plane
;
998 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
1001 drm_modeset_lock_all(dev
);
1003 obj
= drm_mode_object_find(dev
, get
->plane_id
, DRM_MODE_OBJECT_PLANE
);
1009 plane
= obj_to_plane(obj
);
1010 intel_plane
= to_intel_plane(plane
);
1011 intel_plane
->get_colorkey(plane
, get
);
1014 drm_modeset_unlock_all(dev
);
1018 void intel_plane_restore(struct drm_plane
*plane
)
1020 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
1022 if (!plane
->crtc
|| !plane
->fb
)
1025 intel_update_plane(plane
, plane
->crtc
, plane
->fb
,
1026 intel_plane
->crtc_x
, intel_plane
->crtc_y
,
1027 intel_plane
->crtc_w
, intel_plane
->crtc_h
,
1028 intel_plane
->src_x
, intel_plane
->src_y
,
1029 intel_plane
->src_w
, intel_plane
->src_h
);
1032 void intel_plane_disable(struct drm_plane
*plane
)
1034 if (!plane
->crtc
|| !plane
->fb
)
1037 intel_disable_plane(plane
);
1040 static const struct drm_plane_funcs intel_plane_funcs
= {
1041 .update_plane
= intel_update_plane
,
1042 .disable_plane
= intel_disable_plane
,
1043 .destroy
= intel_destroy_plane
,
1046 static uint32_t ilk_plane_formats
[] = {
1047 DRM_FORMAT_XRGB8888
,
1054 static uint32_t snb_plane_formats
[] = {
1055 DRM_FORMAT_XBGR8888
,
1056 DRM_FORMAT_XRGB8888
,
1063 static uint32_t vlv_plane_formats
[] = {
1065 DRM_FORMAT_ABGR8888
,
1066 DRM_FORMAT_ARGB8888
,
1067 DRM_FORMAT_XBGR8888
,
1068 DRM_FORMAT_XRGB8888
,
1069 DRM_FORMAT_XBGR2101010
,
1070 DRM_FORMAT_ABGR2101010
,
1078 intel_plane_init(struct drm_device
*dev
, enum pipe pipe
, int plane
)
1080 struct intel_plane
*intel_plane
;
1081 unsigned long possible_crtcs
;
1082 const uint32_t *plane_formats
;
1083 int num_plane_formats
;
1086 if (INTEL_INFO(dev
)->gen
< 5)
1089 intel_plane
= kzalloc(sizeof(*intel_plane
), GFP_KERNEL
);
1093 switch (INTEL_INFO(dev
)->gen
) {
1096 intel_plane
->can_scale
= true;
1097 intel_plane
->max_downscale
= 16;
1098 intel_plane
->update_plane
= ilk_update_plane
;
1099 intel_plane
->disable_plane
= ilk_disable_plane
;
1100 intel_plane
->update_colorkey
= ilk_update_colorkey
;
1101 intel_plane
->get_colorkey
= ilk_get_colorkey
;
1104 plane_formats
= snb_plane_formats
;
1105 num_plane_formats
= ARRAY_SIZE(snb_plane_formats
);
1107 plane_formats
= ilk_plane_formats
;
1108 num_plane_formats
= ARRAY_SIZE(ilk_plane_formats
);
1114 if (IS_IVYBRIDGE(dev
)) {
1115 intel_plane
->can_scale
= true;
1116 intel_plane
->max_downscale
= 2;
1118 intel_plane
->can_scale
= false;
1119 intel_plane
->max_downscale
= 1;
1122 if (IS_VALLEYVIEW(dev
)) {
1123 intel_plane
->update_plane
= vlv_update_plane
;
1124 intel_plane
->disable_plane
= vlv_disable_plane
;
1125 intel_plane
->update_colorkey
= vlv_update_colorkey
;
1126 intel_plane
->get_colorkey
= vlv_get_colorkey
;
1128 plane_formats
= vlv_plane_formats
;
1129 num_plane_formats
= ARRAY_SIZE(vlv_plane_formats
);
1131 intel_plane
->update_plane
= ivb_update_plane
;
1132 intel_plane
->disable_plane
= ivb_disable_plane
;
1133 intel_plane
->update_colorkey
= ivb_update_colorkey
;
1134 intel_plane
->get_colorkey
= ivb_get_colorkey
;
1136 plane_formats
= snb_plane_formats
;
1137 num_plane_formats
= ARRAY_SIZE(snb_plane_formats
);
1146 intel_plane
->pipe
= pipe
;
1147 intel_plane
->plane
= plane
;
1148 possible_crtcs
= (1 << pipe
);
1149 ret
= drm_plane_init(dev
, &intel_plane
->base
, possible_crtcs
,
1151 plane_formats
, num_plane_formats
,