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_WRITE(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_WRITE(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);
234 sprctl
= I915_READ(SPRCTL(pipe
));
236 /* Mask out pixel format bits in case we change it */
237 sprctl
&= ~SPRITE_PIXFORMAT_MASK
;
238 sprctl
&= ~SPRITE_RGB_ORDER_RGBX
;
239 sprctl
&= ~SPRITE_YUV_BYTE_ORDER_MASK
;
240 sprctl
&= ~SPRITE_TILED
;
242 switch (fb
->pixel_format
) {
243 case DRM_FORMAT_XBGR8888
:
244 sprctl
|= SPRITE_FORMAT_RGBX888
| SPRITE_RGB_ORDER_RGBX
;
246 case DRM_FORMAT_XRGB8888
:
247 sprctl
|= SPRITE_FORMAT_RGBX888
;
249 case DRM_FORMAT_YUYV
:
250 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_YUYV
;
252 case DRM_FORMAT_YVYU
:
253 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_YVYU
;
255 case DRM_FORMAT_UYVY
:
256 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_UYVY
;
258 case DRM_FORMAT_VYUY
:
259 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_VYUY
;
266 * Enable gamma to match primary/cursor plane behaviour.
267 * FIXME should be user controllable via propertiesa.
269 sprctl
|= SPRITE_GAMMA_ENABLE
;
271 if (obj
->tiling_mode
!= I915_TILING_NONE
)
272 sprctl
|= SPRITE_TILED
;
274 if (IS_HASWELL(dev
) || IS_BROADWELL(dev
))
275 sprctl
&= ~SPRITE_TRICKLE_FEED_DISABLE
;
277 sprctl
|= SPRITE_TRICKLE_FEED_DISABLE
;
279 sprctl
|= SPRITE_ENABLE
;
281 if (IS_HASWELL(dev
) || IS_BROADWELL(dev
))
282 sprctl
|= SPRITE_PIPE_CSC_ENABLE
;
284 intel_update_sprite_watermarks(plane
, crtc
, src_w
, pixel_size
, true,
285 src_w
!= crtc_w
|| src_h
!= crtc_h
);
287 /* Sizes are 0 based */
293 if (crtc_w
!= src_w
|| crtc_h
!= src_h
)
294 sprscale
= SPRITE_SCALE_ENABLE
| (src_w
<< 16) | src_h
;
296 I915_WRITE(SPRSTRIDE(pipe
), fb
->pitches
[0]);
297 I915_WRITE(SPRPOS(pipe
), (crtc_y
<< 16) | crtc_x
);
299 linear_offset
= y
* fb
->pitches
[0] + x
* pixel_size
;
301 intel_gen4_compute_page_offset(&x
, &y
, obj
->tiling_mode
,
302 pixel_size
, fb
->pitches
[0]);
303 linear_offset
-= sprsurf_offset
;
305 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
307 if (IS_HASWELL(dev
) || IS_BROADWELL(dev
))
308 I915_WRITE(SPROFFSET(pipe
), (y
<< 16) | x
);
309 else if (obj
->tiling_mode
!= I915_TILING_NONE
)
310 I915_WRITE(SPRTILEOFF(pipe
), (y
<< 16) | x
);
312 I915_WRITE(SPRLINOFF(pipe
), linear_offset
);
314 I915_WRITE(SPRSIZE(pipe
), (crtc_h
<< 16) | crtc_w
);
315 if (intel_plane
->can_scale
)
316 I915_WRITE(SPRSCALE(pipe
), sprscale
);
317 I915_WRITE(SPRCTL(pipe
), sprctl
);
318 I915_WRITE(SPRSURF(pipe
),
319 i915_gem_obj_ggtt_offset(obj
) + sprsurf_offset
);
320 POSTING_READ(SPRSURF(pipe
));
324 ivb_disable_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
)
326 struct drm_device
*dev
= plane
->dev
;
327 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
328 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
329 int pipe
= intel_plane
->pipe
;
331 I915_WRITE(SPRCTL(pipe
), I915_READ(SPRCTL(pipe
)) & ~SPRITE_ENABLE
);
332 /* Can't leave the scaler enabled... */
333 if (intel_plane
->can_scale
)
334 I915_WRITE(SPRSCALE(pipe
), 0);
335 /* Activate double buffered register update */
336 I915_WRITE(SPRSURF(pipe
), 0);
337 POSTING_READ(SPRSURF(pipe
));
340 * Avoid underruns when disabling the sprite.
341 * FIXME remove once watermark updates are done properly.
343 intel_wait_for_vblank(dev
, pipe
);
345 intel_update_sprite_watermarks(plane
, crtc
, 0, 0, false, false);
349 ivb_update_colorkey(struct drm_plane
*plane
,
350 struct drm_intel_sprite_colorkey
*key
)
352 struct drm_device
*dev
= plane
->dev
;
353 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
354 struct intel_plane
*intel_plane
;
358 intel_plane
= to_intel_plane(plane
);
360 I915_WRITE(SPRKEYVAL(intel_plane
->pipe
), key
->min_value
);
361 I915_WRITE(SPRKEYMAX(intel_plane
->pipe
), key
->max_value
);
362 I915_WRITE(SPRKEYMSK(intel_plane
->pipe
), key
->channel_mask
);
364 sprctl
= I915_READ(SPRCTL(intel_plane
->pipe
));
365 sprctl
&= ~(SPRITE_SOURCE_KEY
| SPRITE_DEST_KEY
);
366 if (key
->flags
& I915_SET_COLORKEY_DESTINATION
)
367 sprctl
|= SPRITE_DEST_KEY
;
368 else if (key
->flags
& I915_SET_COLORKEY_SOURCE
)
369 sprctl
|= SPRITE_SOURCE_KEY
;
370 I915_WRITE(SPRCTL(intel_plane
->pipe
), sprctl
);
372 POSTING_READ(SPRKEYMSK(intel_plane
->pipe
));
378 ivb_get_colorkey(struct drm_plane
*plane
, struct drm_intel_sprite_colorkey
*key
)
380 struct drm_device
*dev
= plane
->dev
;
381 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
382 struct intel_plane
*intel_plane
;
385 intel_plane
= to_intel_plane(plane
);
387 key
->min_value
= I915_READ(SPRKEYVAL(intel_plane
->pipe
));
388 key
->max_value
= I915_READ(SPRKEYMAX(intel_plane
->pipe
));
389 key
->channel_mask
= I915_READ(SPRKEYMSK(intel_plane
->pipe
));
392 sprctl
= I915_READ(SPRCTL(intel_plane
->pipe
));
394 if (sprctl
& SPRITE_DEST_KEY
)
395 key
->flags
= I915_SET_COLORKEY_DESTINATION
;
396 else if (sprctl
& SPRITE_SOURCE_KEY
)
397 key
->flags
= I915_SET_COLORKEY_SOURCE
;
399 key
->flags
= I915_SET_COLORKEY_NONE
;
403 ilk_update_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
404 struct drm_framebuffer
*fb
,
405 struct drm_i915_gem_object
*obj
, int crtc_x
, int crtc_y
,
406 unsigned int crtc_w
, unsigned int crtc_h
,
407 uint32_t x
, uint32_t y
,
408 uint32_t src_w
, uint32_t src_h
)
410 struct drm_device
*dev
= plane
->dev
;
411 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
412 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
413 int pipe
= intel_plane
->pipe
;
414 unsigned long dvssurf_offset
, linear_offset
;
415 u32 dvscntr
, dvsscale
;
416 int pixel_size
= drm_format_plane_cpp(fb
->pixel_format
, 0);
418 dvscntr
= I915_READ(DVSCNTR(pipe
));
420 /* Mask out pixel format bits in case we change it */
421 dvscntr
&= ~DVS_PIXFORMAT_MASK
;
422 dvscntr
&= ~DVS_RGB_ORDER_XBGR
;
423 dvscntr
&= ~DVS_YUV_BYTE_ORDER_MASK
;
424 dvscntr
&= ~DVS_TILED
;
426 switch (fb
->pixel_format
) {
427 case DRM_FORMAT_XBGR8888
:
428 dvscntr
|= DVS_FORMAT_RGBX888
| DVS_RGB_ORDER_XBGR
;
430 case DRM_FORMAT_XRGB8888
:
431 dvscntr
|= DVS_FORMAT_RGBX888
;
433 case DRM_FORMAT_YUYV
:
434 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_YUYV
;
436 case DRM_FORMAT_YVYU
:
437 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_YVYU
;
439 case DRM_FORMAT_UYVY
:
440 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_UYVY
;
442 case DRM_FORMAT_VYUY
:
443 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_VYUY
;
450 * Enable gamma to match primary/cursor plane behaviour.
451 * FIXME should be user controllable via propertiesa.
453 dvscntr
|= DVS_GAMMA_ENABLE
;
455 if (obj
->tiling_mode
!= I915_TILING_NONE
)
456 dvscntr
|= DVS_TILED
;
459 dvscntr
|= DVS_TRICKLE_FEED_DISABLE
; /* must disable */
460 dvscntr
|= DVS_ENABLE
;
462 intel_update_sprite_watermarks(plane
, crtc
, src_w
, pixel_size
, true,
463 src_w
!= crtc_w
|| src_h
!= crtc_h
);
465 /* Sizes are 0 based */
472 if (crtc_w
!= src_w
|| crtc_h
!= src_h
)
473 dvsscale
= DVS_SCALE_ENABLE
| (src_w
<< 16) | src_h
;
475 I915_WRITE(DVSSTRIDE(pipe
), fb
->pitches
[0]);
476 I915_WRITE(DVSPOS(pipe
), (crtc_y
<< 16) | crtc_x
);
478 linear_offset
= y
* fb
->pitches
[0] + x
* pixel_size
;
480 intel_gen4_compute_page_offset(&x
, &y
, obj
->tiling_mode
,
481 pixel_size
, fb
->pitches
[0]);
482 linear_offset
-= dvssurf_offset
;
484 if (obj
->tiling_mode
!= I915_TILING_NONE
)
485 I915_WRITE(DVSTILEOFF(pipe
), (y
<< 16) | x
);
487 I915_WRITE(DVSLINOFF(pipe
), linear_offset
);
489 I915_WRITE(DVSSIZE(pipe
), (crtc_h
<< 16) | crtc_w
);
490 I915_WRITE(DVSSCALE(pipe
), dvsscale
);
491 I915_WRITE(DVSCNTR(pipe
), dvscntr
);
492 I915_WRITE(DVSSURF(pipe
),
493 i915_gem_obj_ggtt_offset(obj
) + dvssurf_offset
);
494 POSTING_READ(DVSSURF(pipe
));
498 ilk_disable_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
)
500 struct drm_device
*dev
= plane
->dev
;
501 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
502 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
503 int pipe
= intel_plane
->pipe
;
505 I915_WRITE(DVSCNTR(pipe
), I915_READ(DVSCNTR(pipe
)) & ~DVS_ENABLE
);
506 /* Disable the scaler */
507 I915_WRITE(DVSSCALE(pipe
), 0);
508 /* Flush double buffered register updates */
509 I915_WRITE(DVSSURF(pipe
), 0);
510 POSTING_READ(DVSSURF(pipe
));
513 * Avoid underruns when disabling the sprite.
514 * FIXME remove once watermark updates are done properly.
516 intel_wait_for_vblank(dev
, pipe
);
518 intel_update_sprite_watermarks(plane
, crtc
, 0, 0, false, false);
522 intel_enable_primary(struct drm_crtc
*crtc
)
524 struct drm_device
*dev
= crtc
->dev
;
525 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
526 struct intel_crtc
*intel_crtc
= to_intel_crtc(crtc
);
527 int reg
= DSPCNTR(intel_crtc
->plane
);
529 if (intel_crtc
->primary_enabled
)
532 intel_crtc
->primary_enabled
= true;
534 I915_WRITE(reg
, I915_READ(reg
) | DISPLAY_PLANE_ENABLE
);
535 intel_flush_primary_plane(dev_priv
, intel_crtc
->plane
);
538 * FIXME IPS should be fine as long as one plane is
539 * enabled, but in practice it seems to have problems
540 * when going from primary only to sprite only and vice
543 if (intel_crtc
->config
.ips_enabled
) {
544 intel_wait_for_vblank(dev
, intel_crtc
->pipe
);
545 hsw_enable_ips(intel_crtc
);
548 mutex_lock(&dev
->struct_mutex
);
549 intel_update_fbc(dev
);
550 mutex_unlock(&dev
->struct_mutex
);
554 intel_disable_primary(struct drm_crtc
*crtc
)
556 struct drm_device
*dev
= crtc
->dev
;
557 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
558 struct intel_crtc
*intel_crtc
= to_intel_crtc(crtc
);
559 int reg
= DSPCNTR(intel_crtc
->plane
);
561 if (!intel_crtc
->primary_enabled
)
564 intel_crtc
->primary_enabled
= false;
566 mutex_lock(&dev
->struct_mutex
);
567 if (dev_priv
->fbc
.plane
== intel_crtc
->plane
)
568 intel_disable_fbc(dev
);
569 mutex_unlock(&dev
->struct_mutex
);
572 * FIXME IPS should be fine as long as one plane is
573 * enabled, but in practice it seems to have problems
574 * when going from primary only to sprite only and vice
577 hsw_disable_ips(intel_crtc
);
579 I915_WRITE(reg
, I915_READ(reg
) & ~DISPLAY_PLANE_ENABLE
);
580 intel_flush_primary_plane(dev_priv
, intel_crtc
->plane
);
584 ilk_update_colorkey(struct drm_plane
*plane
,
585 struct drm_intel_sprite_colorkey
*key
)
587 struct drm_device
*dev
= plane
->dev
;
588 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
589 struct intel_plane
*intel_plane
;
593 intel_plane
= to_intel_plane(plane
);
595 I915_WRITE(DVSKEYVAL(intel_plane
->pipe
), key
->min_value
);
596 I915_WRITE(DVSKEYMAX(intel_plane
->pipe
), key
->max_value
);
597 I915_WRITE(DVSKEYMSK(intel_plane
->pipe
), key
->channel_mask
);
599 dvscntr
= I915_READ(DVSCNTR(intel_plane
->pipe
));
600 dvscntr
&= ~(DVS_SOURCE_KEY
| DVS_DEST_KEY
);
601 if (key
->flags
& I915_SET_COLORKEY_DESTINATION
)
602 dvscntr
|= DVS_DEST_KEY
;
603 else if (key
->flags
& I915_SET_COLORKEY_SOURCE
)
604 dvscntr
|= DVS_SOURCE_KEY
;
605 I915_WRITE(DVSCNTR(intel_plane
->pipe
), dvscntr
);
607 POSTING_READ(DVSKEYMSK(intel_plane
->pipe
));
613 ilk_get_colorkey(struct drm_plane
*plane
, struct drm_intel_sprite_colorkey
*key
)
615 struct drm_device
*dev
= plane
->dev
;
616 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
617 struct intel_plane
*intel_plane
;
620 intel_plane
= to_intel_plane(plane
);
622 key
->min_value
= I915_READ(DVSKEYVAL(intel_plane
->pipe
));
623 key
->max_value
= I915_READ(DVSKEYMAX(intel_plane
->pipe
));
624 key
->channel_mask
= I915_READ(DVSKEYMSK(intel_plane
->pipe
));
627 dvscntr
= I915_READ(DVSCNTR(intel_plane
->pipe
));
629 if (dvscntr
& DVS_DEST_KEY
)
630 key
->flags
= I915_SET_COLORKEY_DESTINATION
;
631 else if (dvscntr
& DVS_SOURCE_KEY
)
632 key
->flags
= I915_SET_COLORKEY_SOURCE
;
634 key
->flags
= I915_SET_COLORKEY_NONE
;
638 format_is_yuv(uint32_t format
)
641 case DRM_FORMAT_YUYV
:
642 case DRM_FORMAT_UYVY
:
643 case DRM_FORMAT_VYUY
:
644 case DRM_FORMAT_YVYU
:
651 static bool colorkey_enabled(struct intel_plane
*intel_plane
)
653 struct drm_intel_sprite_colorkey key
;
655 intel_plane
->get_colorkey(&intel_plane
->base
, &key
);
657 return key
.flags
!= I915_SET_COLORKEY_NONE
;
661 intel_update_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
662 struct drm_framebuffer
*fb
, int crtc_x
, int crtc_y
,
663 unsigned int crtc_w
, unsigned int crtc_h
,
664 uint32_t src_x
, uint32_t src_y
,
665 uint32_t src_w
, uint32_t src_h
)
667 struct drm_device
*dev
= plane
->dev
;
668 struct intel_crtc
*intel_crtc
= to_intel_crtc(crtc
);
669 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
670 struct intel_framebuffer
*intel_fb
= to_intel_framebuffer(fb
);
671 struct drm_i915_gem_object
*obj
= intel_fb
->obj
;
672 struct drm_i915_gem_object
*old_obj
= intel_plane
->obj
;
674 bool disable_primary
= false;
677 int max_scale
, min_scale
;
678 int pixel_size
= drm_format_plane_cpp(fb
->pixel_format
, 0);
679 struct drm_rect src
= {
680 /* sample coordinates in 16.16 fixed point */
686 struct drm_rect dst
= {
689 .x2
= crtc_x
+ crtc_w
,
691 .y2
= crtc_y
+ crtc_h
,
693 const struct drm_rect clip
= {
694 .x2
= intel_crtc
->active
? intel_crtc
->config
.pipe_src_w
: 0,
695 .y2
= intel_crtc
->active
? intel_crtc
->config
.pipe_src_h
: 0,
699 unsigned int crtc_w
, crtc_h
;
700 uint32_t src_x
, src_y
, src_w
, src_h
;
712 /* Don't modify another pipe's plane */
713 if (intel_plane
->pipe
!= intel_crtc
->pipe
) {
714 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
718 /* FIXME check all gen limits */
719 if (fb
->width
< 3 || fb
->height
< 3 || fb
->pitches
[0] > 16384) {
720 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
724 /* Sprite planes can be linear or x-tiled surfaces */
725 switch (obj
->tiling_mode
) {
726 case I915_TILING_NONE
:
730 DRM_DEBUG_KMS("Unsupported tiling mode\n");
735 * FIXME the following code does a bunch of fuzzy adjustments to the
736 * coordinates and sizes. We probably need some way to decide whether
737 * more strict checking should be done instead.
739 max_scale
= intel_plane
->max_downscale
<< 16;
740 min_scale
= intel_plane
->can_scale
? 1 : (1 << 16);
742 hscale
= drm_rect_calc_hscale_relaxed(&src
, &dst
, min_scale
, max_scale
);
745 vscale
= drm_rect_calc_vscale_relaxed(&src
, &dst
, min_scale
, max_scale
);
748 visible
= drm_rect_clip_scaled(&src
, &dst
, &clip
, hscale
, vscale
);
752 crtc_w
= drm_rect_width(&dst
);
753 crtc_h
= drm_rect_height(&dst
);
756 /* check again in case clipping clamped the results */
757 hscale
= drm_rect_calc_hscale(&src
, &dst
, min_scale
, max_scale
);
759 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
760 drm_rect_debug_print(&src
, true);
761 drm_rect_debug_print(&dst
, false);
766 vscale
= drm_rect_calc_vscale(&src
, &dst
, min_scale
, max_scale
);
768 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
769 drm_rect_debug_print(&src
, true);
770 drm_rect_debug_print(&dst
, false);
775 /* Make the source viewport size an exact multiple of the scaling factors. */
776 drm_rect_adjust_size(&src
,
777 drm_rect_width(&dst
) * hscale
- drm_rect_width(&src
),
778 drm_rect_height(&dst
) * vscale
- drm_rect_height(&src
));
780 /* sanity check to make sure the src viewport wasn't enlarged */
781 WARN_ON(src
.x1
< (int) src_x
||
782 src
.y1
< (int) src_y
||
783 src
.x2
> (int) (src_x
+ src_w
) ||
784 src
.y2
> (int) (src_y
+ src_h
));
787 * Hardware doesn't handle subpixel coordinates.
788 * Adjust to (macro)pixel boundary, but be careful not to
789 * increase the source viewport size, because that could
790 * push the downscaling factor out of bounds.
792 src_x
= src
.x1
>> 16;
793 src_w
= drm_rect_width(&src
) >> 16;
794 src_y
= src
.y1
>> 16;
795 src_h
= drm_rect_height(&src
) >> 16;
797 if (format_is_yuv(fb
->pixel_format
)) {
802 * Must keep src and dst the
803 * same if we can't scale.
805 if (!intel_plane
->can_scale
)
813 /* Check size restrictions when scaling */
814 if (visible
&& (src_w
!= crtc_w
|| src_h
!= crtc_h
)) {
815 unsigned int width_bytes
;
817 WARN_ON(!intel_plane
->can_scale
);
819 /* FIXME interlacing min height is 6 */
821 if (crtc_w
< 3 || crtc_h
< 3)
824 if (src_w
< 3 || src_h
< 3)
827 width_bytes
= ((src_x
* pixel_size
) & 63) + src_w
* pixel_size
;
829 if (src_w
> 2048 || src_h
> 2048 ||
830 width_bytes
> 4096 || fb
->pitches
[0] > 4096) {
831 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
837 dst
.x2
= crtc_x
+ crtc_w
;
839 dst
.y2
= crtc_y
+ crtc_h
;
842 * If the sprite is completely covering the primary plane,
843 * we can disable the primary and save power.
845 disable_primary
= drm_rect_equals(&dst
, &clip
) && !colorkey_enabled(intel_plane
);
846 WARN_ON(disable_primary
&& !visible
&& intel_crtc
->active
);
848 mutex_lock(&dev
->struct_mutex
);
850 /* Note that this will apply the VT-d workaround for scanouts,
851 * which is more restrictive than required for sprites. (The
852 * primary plane requires 256KiB alignment with 64 PTE padding,
853 * the sprite planes only require 128KiB alignment and 32 PTE padding.
855 ret
= intel_pin_and_fence_fb_obj(dev
, obj
, NULL
);
857 mutex_unlock(&dev
->struct_mutex
);
862 intel_plane
->crtc_x
= orig
.crtc_x
;
863 intel_plane
->crtc_y
= orig
.crtc_y
;
864 intel_plane
->crtc_w
= orig
.crtc_w
;
865 intel_plane
->crtc_h
= orig
.crtc_h
;
866 intel_plane
->src_x
= orig
.src_x
;
867 intel_plane
->src_y
= orig
.src_y
;
868 intel_plane
->src_w
= orig
.src_w
;
869 intel_plane
->src_h
= orig
.src_h
;
870 intel_plane
->obj
= obj
;
872 if (intel_crtc
->active
) {
874 * Be sure to re-enable the primary before the sprite is no longer
877 if (!disable_primary
)
878 intel_enable_primary(crtc
);
881 intel_plane
->update_plane(plane
, crtc
, fb
, obj
,
882 crtc_x
, crtc_y
, crtc_w
, crtc_h
,
883 src_x
, src_y
, src_w
, src_h
);
885 intel_plane
->disable_plane(plane
, crtc
);
888 intel_disable_primary(crtc
);
891 /* Unpin old obj after new one is active to avoid ugliness */
894 * It's fairly common to simply update the position of
895 * an existing object. In that case, we don't need to
896 * wait for vblank to avoid ugliness, we only need to
897 * do the pin & ref bookkeeping.
899 if (old_obj
!= obj
&& intel_crtc
->active
)
900 intel_wait_for_vblank(dev
, intel_crtc
->pipe
);
902 mutex_lock(&dev
->struct_mutex
);
903 intel_unpin_fb_obj(old_obj
);
904 mutex_unlock(&dev
->struct_mutex
);
911 intel_disable_plane(struct drm_plane
*plane
)
913 struct drm_device
*dev
= plane
->dev
;
914 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
915 struct intel_crtc
*intel_crtc
;
920 if (WARN_ON(!plane
->crtc
))
923 intel_crtc
= to_intel_crtc(plane
->crtc
);
925 if (intel_crtc
->active
) {
926 intel_enable_primary(plane
->crtc
);
927 intel_plane
->disable_plane(plane
, plane
->crtc
);
930 if (intel_plane
->obj
) {
931 if (intel_crtc
->active
)
932 intel_wait_for_vblank(dev
, intel_plane
->pipe
);
934 mutex_lock(&dev
->struct_mutex
);
935 intel_unpin_fb_obj(intel_plane
->obj
);
936 mutex_unlock(&dev
->struct_mutex
);
938 intel_plane
->obj
= NULL
;
944 static void intel_destroy_plane(struct drm_plane
*plane
)
946 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
947 intel_disable_plane(plane
);
948 drm_plane_cleanup(plane
);
952 int intel_sprite_set_colorkey(struct drm_device
*dev
, void *data
,
953 struct drm_file
*file_priv
)
955 struct drm_intel_sprite_colorkey
*set
= data
;
956 struct drm_mode_object
*obj
;
957 struct drm_plane
*plane
;
958 struct intel_plane
*intel_plane
;
961 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
964 /* Make sure we don't try to enable both src & dest simultaneously */
965 if ((set
->flags
& (I915_SET_COLORKEY_DESTINATION
| I915_SET_COLORKEY_SOURCE
)) == (I915_SET_COLORKEY_DESTINATION
| I915_SET_COLORKEY_SOURCE
))
968 drm_modeset_lock_all(dev
);
970 obj
= drm_mode_object_find(dev
, set
->plane_id
, DRM_MODE_OBJECT_PLANE
);
976 plane
= obj_to_plane(obj
);
977 intel_plane
= to_intel_plane(plane
);
978 ret
= intel_plane
->update_colorkey(plane
, set
);
981 drm_modeset_unlock_all(dev
);
985 int intel_sprite_get_colorkey(struct drm_device
*dev
, void *data
,
986 struct drm_file
*file_priv
)
988 struct drm_intel_sprite_colorkey
*get
= data
;
989 struct drm_mode_object
*obj
;
990 struct drm_plane
*plane
;
991 struct intel_plane
*intel_plane
;
994 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
997 drm_modeset_lock_all(dev
);
999 obj
= drm_mode_object_find(dev
, get
->plane_id
, DRM_MODE_OBJECT_PLANE
);
1005 plane
= obj_to_plane(obj
);
1006 intel_plane
= to_intel_plane(plane
);
1007 intel_plane
->get_colorkey(plane
, get
);
1010 drm_modeset_unlock_all(dev
);
1014 void intel_plane_restore(struct drm_plane
*plane
)
1016 struct intel_plane
*intel_plane
= to_intel_plane(plane
);
1018 if (!plane
->crtc
|| !plane
->fb
)
1021 intel_update_plane(plane
, plane
->crtc
, plane
->fb
,
1022 intel_plane
->crtc_x
, intel_plane
->crtc_y
,
1023 intel_plane
->crtc_w
, intel_plane
->crtc_h
,
1024 intel_plane
->src_x
, intel_plane
->src_y
,
1025 intel_plane
->src_w
, intel_plane
->src_h
);
1028 void intel_plane_disable(struct drm_plane
*plane
)
1030 if (!plane
->crtc
|| !plane
->fb
)
1033 intel_disable_plane(plane
);
1036 static const struct drm_plane_funcs intel_plane_funcs
= {
1037 .update_plane
= intel_update_plane
,
1038 .disable_plane
= intel_disable_plane
,
1039 .destroy
= intel_destroy_plane
,
1042 static uint32_t ilk_plane_formats
[] = {
1043 DRM_FORMAT_XRGB8888
,
1050 static uint32_t snb_plane_formats
[] = {
1051 DRM_FORMAT_XBGR8888
,
1052 DRM_FORMAT_XRGB8888
,
1059 static uint32_t vlv_plane_formats
[] = {
1061 DRM_FORMAT_ABGR8888
,
1062 DRM_FORMAT_ARGB8888
,
1063 DRM_FORMAT_XBGR8888
,
1064 DRM_FORMAT_XRGB8888
,
1065 DRM_FORMAT_XBGR2101010
,
1066 DRM_FORMAT_ABGR2101010
,
1074 intel_plane_init(struct drm_device
*dev
, enum pipe pipe
, int plane
)
1076 struct intel_plane
*intel_plane
;
1077 unsigned long possible_crtcs
;
1078 const uint32_t *plane_formats
;
1079 int num_plane_formats
;
1082 if (INTEL_INFO(dev
)->gen
< 5)
1085 intel_plane
= kzalloc(sizeof(*intel_plane
), GFP_KERNEL
);
1089 switch (INTEL_INFO(dev
)->gen
) {
1092 intel_plane
->can_scale
= true;
1093 intel_plane
->max_downscale
= 16;
1094 intel_plane
->update_plane
= ilk_update_plane
;
1095 intel_plane
->disable_plane
= ilk_disable_plane
;
1096 intel_plane
->update_colorkey
= ilk_update_colorkey
;
1097 intel_plane
->get_colorkey
= ilk_get_colorkey
;
1100 plane_formats
= snb_plane_formats
;
1101 num_plane_formats
= ARRAY_SIZE(snb_plane_formats
);
1103 plane_formats
= ilk_plane_formats
;
1104 num_plane_formats
= ARRAY_SIZE(ilk_plane_formats
);
1110 if (IS_IVYBRIDGE(dev
)) {
1111 intel_plane
->can_scale
= true;
1112 intel_plane
->max_downscale
= 2;
1114 intel_plane
->can_scale
= false;
1115 intel_plane
->max_downscale
= 1;
1118 if (IS_VALLEYVIEW(dev
)) {
1119 intel_plane
->update_plane
= vlv_update_plane
;
1120 intel_plane
->disable_plane
= vlv_disable_plane
;
1121 intel_plane
->update_colorkey
= vlv_update_colorkey
;
1122 intel_plane
->get_colorkey
= vlv_get_colorkey
;
1124 plane_formats
= vlv_plane_formats
;
1125 num_plane_formats
= ARRAY_SIZE(vlv_plane_formats
);
1127 intel_plane
->update_plane
= ivb_update_plane
;
1128 intel_plane
->disable_plane
= ivb_disable_plane
;
1129 intel_plane
->update_colorkey
= ivb_update_colorkey
;
1130 intel_plane
->get_colorkey
= ivb_get_colorkey
;
1132 plane_formats
= snb_plane_formats
;
1133 num_plane_formats
= ARRAY_SIZE(snb_plane_formats
);
1142 intel_plane
->pipe
= pipe
;
1143 intel_plane
->plane
= plane
;
1144 possible_crtcs
= (1 << pipe
);
1145 ret
= drm_plane_init(dev
, &intel_plane
->base
, possible_crtcs
,
1147 plane_formats
, num_plane_formats
,