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_atomic.h>
34 #include <drm/drm_atomic_helper.h>
35 #include <drm/drm_color_mgmt.h>
36 #include <drm/drm_crtc.h>
37 #include <drm/drm_damage_helper.h>
38 #include <drm/drm_fourcc.h>
39 #include <drm/drm_plane_helper.h>
40 #include <drm/drm_rect.h>
43 #include "i915_vgpu.h"
44 #include "i9xx_plane.h"
45 #include "intel_atomic_plane.h"
46 #include "intel_crtc.h"
48 #include "intel_display_types.h"
50 #include "intel_frontbuffer.h"
51 #include "intel_sprite.h"
52 #include "intel_vrr.h"
54 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
56 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
57 const struct drm_framebuffer *fb = plane_state->hw.fb;
58 struct drm_rect *src = &plane_state->uapi.src;
59 u32 src_x, src_y, src_w, src_h, hsub, vsub;
60 bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
63 * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
64 * abuses hsub/vsub so we can't use them here. But as they
65 * are limited to 32bpp RGB formats we don't actually need
68 if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
69 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
73 * Hardware doesn't handle subpixel coordinates.
74 * Adjust to (macro)pixel boundary, but be careful not to
75 * increase the source viewport size, because that could
76 * push the downscaling factor out of bounds.
78 src_x = src->x1 >> 16;
79 src_w = drm_rect_width(src) >> 16;
80 src_y = src->y1 >> 16;
81 src_h = drm_rect_height(src) >> 16;
83 drm_rect_init(src, src_x << 16, src_y << 16,
84 src_w << 16, src_h << 16);
86 if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
90 hsub = fb->format->hsub;
91 vsub = fb->format->vsub;
95 hsub = vsub = max(hsub, vsub);
97 if (src_x % hsub || src_w % hsub) {
98 drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
99 src_x, src_w, hsub, yesno(rotated));
103 if (src_y % vsub || src_h % vsub) {
104 drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
105 src_y, src_h, vsub, yesno(rotated));
112 static void i9xx_plane_linear_gamma(u16 gamma[8])
114 /* The points are not evenly spaced. */
115 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
118 for (i = 0; i < 8; i++)
119 gamma[i] = (in[i] << 8) / 32;
123 chv_sprite_update_csc(const struct intel_plane_state *plane_state)
125 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
126 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
127 const struct drm_framebuffer *fb = plane_state->hw.fb;
128 enum plane_id plane_id = plane->id;
130 * |r| | c0 c1 c2 | |cr|
131 * |g| = | c3 c4 c5 | x |y |
132 * |b| | c6 c7 c8 | |cb|
134 * Coefficients are s3.12.
136 * Cb and Cr apparently come in as signed already, and
137 * we always get full range data in on account of CLRC0/1.
139 static const s16 csc_matrix[][9] = {
140 /* BT.601 full range YCbCr -> full range RGB */
141 [DRM_COLOR_YCBCR_BT601] = {
146 /* BT.709 full range YCbCr -> full range RGB */
147 [DRM_COLOR_YCBCR_BT709] = {
153 const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
155 /* Seems RGB data bypasses the CSC always */
156 if (!fb->format->is_yuv)
159 intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
160 SPCSC_OOFF(0) | SPCSC_IOFF(0));
161 intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
162 SPCSC_OOFF(0) | SPCSC_IOFF(0));
163 intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
164 SPCSC_OOFF(0) | SPCSC_IOFF(0));
166 intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
167 SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
168 intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
169 SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
170 intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
171 SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
172 intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
173 SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
174 intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
176 intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
177 SPCSC_IMAX(1023) | SPCSC_IMIN(0));
178 intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
179 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
180 intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
181 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
183 intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
184 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
185 intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
186 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
187 intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
188 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
195 vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
197 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
198 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
199 const struct drm_framebuffer *fb = plane_state->hw.fb;
200 enum pipe pipe = plane->pipe;
201 enum plane_id plane_id = plane->id;
202 int contrast, brightness, sh_scale, sh_sin, sh_cos;
204 if (fb->format->is_yuv &&
205 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
207 * Expand limited range to full range:
208 * Contrast is applied first and is used to expand Y range.
209 * Brightness is applied second and is used to remove the
210 * offset from Y. Saturation/hue is used to expand CbCr range.
212 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
213 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
214 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
215 sh_sin = SIN_0 * sh_scale;
216 sh_cos = COS_0 * sh_scale;
218 /* Pass-through everything. */
222 sh_sin = SIN_0 * sh_scale;
223 sh_cos = COS_0 * sh_scale;
226 /* FIXME these register are single buffered :( */
227 intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
228 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
229 intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
230 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
234 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
235 const struct intel_plane_state *plane_state,
236 unsigned int *num, unsigned int *den)
238 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
239 const struct drm_framebuffer *fb = plane_state->hw.fb;
240 unsigned int cpp = fb->format->cpp[0];
243 * VLV bspec only considers cases where all three planes are
244 * enabled, and cases where the primary and one sprite is enabled.
245 * Let's assume the case with just two sprites enabled also
246 * maps to the latter case.
248 if (hweight8(active_planes) == 3) {
263 } else if (hweight8(active_planes) == 2) {
292 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
293 const struct intel_plane_state *plane_state)
295 unsigned int pixel_rate;
296 unsigned int num, den;
299 * Note that crtc_state->pixel_rate accounts for both
300 * horizontal and vertical panel fitter downscaling factors.
301 * Pre-HSW bspec tells us to only consider the horizontal
302 * downscaling factor here. We ignore that and just consider
303 * both for simplicity.
305 pixel_rate = crtc_state->pixel_rate;
307 vlv_plane_ratio(crtc_state, plane_state, &num, &den);
309 return DIV_ROUND_UP(pixel_rate * num, den);
312 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
316 if (crtc_state->gamma_enable)
317 sprctl |= SP_PIPE_GAMMA_ENABLE;
322 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
323 const struct intel_plane_state *plane_state)
325 const struct drm_framebuffer *fb = plane_state->hw.fb;
326 unsigned int rotation = plane_state->hw.rotation;
327 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
332 switch (fb->format->format) {
333 case DRM_FORMAT_YUYV:
334 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
336 case DRM_FORMAT_YVYU:
337 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
339 case DRM_FORMAT_UYVY:
340 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
342 case DRM_FORMAT_VYUY:
343 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
346 sprctl |= SP_FORMAT_8BPP;
348 case DRM_FORMAT_RGB565:
349 sprctl |= SP_FORMAT_BGR565;
351 case DRM_FORMAT_XRGB8888:
352 sprctl |= SP_FORMAT_BGRX8888;
354 case DRM_FORMAT_ARGB8888:
355 sprctl |= SP_FORMAT_BGRA8888;
357 case DRM_FORMAT_XBGR2101010:
358 sprctl |= SP_FORMAT_RGBX1010102;
360 case DRM_FORMAT_ABGR2101010:
361 sprctl |= SP_FORMAT_RGBA1010102;
363 case DRM_FORMAT_XRGB2101010:
364 sprctl |= SP_FORMAT_BGRX1010102;
366 case DRM_FORMAT_ARGB2101010:
367 sprctl |= SP_FORMAT_BGRA1010102;
369 case DRM_FORMAT_XBGR8888:
370 sprctl |= SP_FORMAT_RGBX8888;
372 case DRM_FORMAT_ABGR8888:
373 sprctl |= SP_FORMAT_RGBA8888;
376 MISSING_CASE(fb->format->format);
380 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
381 sprctl |= SP_YUV_FORMAT_BT709;
383 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
386 if (rotation & DRM_MODE_ROTATE_180)
387 sprctl |= SP_ROTATE_180;
389 if (rotation & DRM_MODE_REFLECT_X)
392 if (key->flags & I915_SET_COLORKEY_SOURCE)
393 sprctl |= SP_SOURCE_KEY;
398 static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
400 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
401 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
402 const struct drm_framebuffer *fb = plane_state->hw.fb;
403 enum pipe pipe = plane->pipe;
404 enum plane_id plane_id = plane->id;
408 /* Seems RGB data bypasses the gamma always */
409 if (!fb->format->is_yuv)
412 i9xx_plane_linear_gamma(gamma);
414 /* FIXME these register are single buffered :( */
415 /* The two end points are implicit (0.0 and 1.0) */
416 for (i = 1; i < 8 - 1; i++)
417 intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
418 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
422 vlv_sprite_update_noarm(struct intel_plane *plane,
423 const struct intel_crtc_state *crtc_state,
424 const struct intel_plane_state *plane_state)
426 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
427 enum pipe pipe = plane->pipe;
428 enum plane_id plane_id = plane->id;
429 int crtc_x = plane_state->uapi.dst.x1;
430 int crtc_y = plane_state->uapi.dst.y1;
431 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
432 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
433 unsigned long irqflags;
435 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
437 intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
438 plane_state->view.color_plane[0].mapping_stride);
439 intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
440 SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
441 intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
442 SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
444 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
448 vlv_sprite_update_arm(struct intel_plane *plane,
449 const struct intel_crtc_state *crtc_state,
450 const struct intel_plane_state *plane_state)
452 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
453 enum pipe pipe = plane->pipe;
454 enum plane_id plane_id = plane->id;
455 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
456 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
457 u32 x = plane_state->view.color_plane[0].x;
458 u32 y = plane_state->view.color_plane[0].y;
459 u32 sprctl, linear_offset;
460 unsigned long irqflags;
462 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
464 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
466 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
468 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
469 chv_sprite_update_csc(plane_state);
472 intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
474 intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
476 intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
480 intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
482 intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
483 intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id),
484 SP_OFFSET_Y(y) | SP_OFFSET_X(x));
487 * The control register self-arms if the plane was previously
488 * disabled. Try to make the plane enable atomic by writing
489 * the control register just before the surface register.
491 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
492 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
493 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
495 vlv_sprite_update_clrc(plane_state);
496 vlv_sprite_update_gamma(plane_state);
498 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
502 vlv_sprite_disable_arm(struct intel_plane *plane,
503 const struct intel_crtc_state *crtc_state)
505 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
506 enum pipe pipe = plane->pipe;
507 enum plane_id plane_id = plane->id;
508 unsigned long irqflags;
510 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
512 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
513 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
515 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
519 vlv_sprite_get_hw_state(struct intel_plane *plane,
522 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
523 enum intel_display_power_domain power_domain;
524 enum plane_id plane_id = plane->id;
525 intel_wakeref_t wakeref;
528 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
529 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
533 ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
537 intel_display_power_put(dev_priv, power_domain, wakeref);
542 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
543 const struct intel_plane_state *plane_state,
544 unsigned int *num, unsigned int *den)
546 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
547 const struct drm_framebuffer *fb = plane_state->hw.fb;
548 unsigned int cpp = fb->format->cpp[0];
550 if (hweight8(active_planes) == 2) {
579 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
580 const struct intel_plane_state *plane_state,
581 unsigned int *num, unsigned int *den)
583 const struct drm_framebuffer *fb = plane_state->hw.fb;
584 unsigned int cpp = fb->format->cpp[0];
606 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
607 const struct intel_plane_state *plane_state)
609 unsigned int pixel_rate;
610 unsigned int num, den;
613 * Note that crtc_state->pixel_rate accounts for both
614 * horizontal and vertical panel fitter downscaling factors.
615 * Pre-HSW bspec tells us to only consider the horizontal
616 * downscaling factor here. We ignore that and just consider
617 * both for simplicity.
619 pixel_rate = crtc_state->pixel_rate;
621 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
623 return DIV_ROUND_UP(pixel_rate * num, den);
626 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
627 const struct intel_plane_state *plane_state)
629 unsigned int src_w, dst_w, pixel_rate;
630 unsigned int num, den;
633 * Note that crtc_state->pixel_rate accounts for both
634 * horizontal and vertical panel fitter downscaling factors.
635 * Pre-HSW bspec tells us to only consider the horizontal
636 * downscaling factor here. We ignore that and just consider
637 * both for simplicity.
639 pixel_rate = crtc_state->pixel_rate;
641 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
642 dst_w = drm_rect_width(&plane_state->uapi.dst);
645 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
647 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
649 /* Horizontal downscaling limits the maximum pixel rate */
650 dst_w = min(src_w, dst_w);
652 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
656 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
657 const struct intel_plane_state *plane_state,
658 unsigned int *num, unsigned int *den)
660 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
661 const struct drm_framebuffer *fb = plane_state->hw.fb;
662 unsigned int cpp = fb->format->cpp[0];
664 if (hweight8(active_planes) == 2) {
689 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
690 const struct intel_plane_state *plane_state)
692 unsigned int pixel_rate = crtc_state->pixel_rate;
693 unsigned int num, den;
695 hsw_plane_ratio(crtc_state, plane_state, &num, &den);
697 return DIV_ROUND_UP(pixel_rate * num, den);
700 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
704 if (crtc_state->gamma_enable)
705 sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
707 if (crtc_state->csc_enable)
708 sprctl |= SPRITE_PIPE_CSC_ENABLE;
713 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
715 struct drm_i915_private *dev_priv =
716 to_i915(plane_state->uapi.plane->dev);
717 const struct drm_framebuffer *fb = plane_state->hw.fb;
719 return fb->format->cpp[0] == 8 &&
720 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
723 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
724 const struct intel_plane_state *plane_state)
726 struct drm_i915_private *dev_priv =
727 to_i915(plane_state->uapi.plane->dev);
728 const struct drm_framebuffer *fb = plane_state->hw.fb;
729 unsigned int rotation = plane_state->hw.rotation;
730 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
733 sprctl = SPRITE_ENABLE;
735 if (IS_IVYBRIDGE(dev_priv))
736 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
738 switch (fb->format->format) {
739 case DRM_FORMAT_XBGR8888:
740 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
742 case DRM_FORMAT_XRGB8888:
743 sprctl |= SPRITE_FORMAT_RGBX888;
745 case DRM_FORMAT_XBGR2101010:
746 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
748 case DRM_FORMAT_XRGB2101010:
749 sprctl |= SPRITE_FORMAT_RGBX101010;
751 case DRM_FORMAT_XBGR16161616F:
752 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
754 case DRM_FORMAT_XRGB16161616F:
755 sprctl |= SPRITE_FORMAT_RGBX161616;
757 case DRM_FORMAT_YUYV:
758 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
760 case DRM_FORMAT_YVYU:
761 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
763 case DRM_FORMAT_UYVY:
764 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
766 case DRM_FORMAT_VYUY:
767 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
770 MISSING_CASE(fb->format->format);
774 if (!ivb_need_sprite_gamma(plane_state))
775 sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
777 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
778 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
780 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
781 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
783 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
784 sprctl |= SPRITE_TILED;
786 if (rotation & DRM_MODE_ROTATE_180)
787 sprctl |= SPRITE_ROTATE_180;
789 if (key->flags & I915_SET_COLORKEY_DESTINATION)
790 sprctl |= SPRITE_DEST_KEY;
791 else if (key->flags & I915_SET_COLORKEY_SOURCE)
792 sprctl |= SPRITE_SOURCE_KEY;
797 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
803 * WaFP16GammaEnabling:ivb,hsw
804 * "Workaround : When using the 64-bit format, the sprite output
805 * on each color channel has one quarter amplitude. It can be
806 * brought up to full amplitude by using sprite internal gamma
807 * correction, pipe gamma correction, or pipe color space
808 * conversion to multiply the sprite output by four."
812 for (i = 0; i < 16; i++)
813 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
815 gamma[i] = min((scale * i << 10) / 16, 1 << 10);
822 static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
824 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
825 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
826 enum pipe pipe = plane->pipe;
830 if (!ivb_need_sprite_gamma(plane_state))
833 ivb_sprite_linear_gamma(plane_state, gamma);
835 /* FIXME these register are single buffered :( */
836 for (i = 0; i < 16; i++)
837 intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
838 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
840 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
841 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
842 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
845 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
846 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
847 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
852 ivb_sprite_update_noarm(struct intel_plane *plane,
853 const struct intel_crtc_state *crtc_state,
854 const struct intel_plane_state *plane_state)
856 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
857 enum pipe pipe = plane->pipe;
858 int crtc_x = plane_state->uapi.dst.x1;
859 int crtc_y = plane_state->uapi.dst.y1;
860 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
861 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
862 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
863 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
865 unsigned long irqflags;
867 if (crtc_w != src_w || crtc_h != src_h)
868 sprscale = SPRITE_SCALE_ENABLE |
869 SPRITE_SRC_WIDTH(src_w - 1) |
870 SPRITE_SRC_HEIGHT(src_h - 1);
872 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
874 intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
875 plane_state->view.color_plane[0].mapping_stride);
876 intel_de_write_fw(dev_priv, SPRPOS(pipe),
877 SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
878 intel_de_write_fw(dev_priv, SPRSIZE(pipe),
879 SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
880 if (IS_IVYBRIDGE(dev_priv))
881 intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
883 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
887 ivb_sprite_update_arm(struct intel_plane *plane,
888 const struct intel_crtc_state *crtc_state,
889 const struct intel_plane_state *plane_state)
891 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
892 enum pipe pipe = plane->pipe;
893 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
894 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
895 u32 x = plane_state->view.color_plane[0].x;
896 u32 y = plane_state->view.color_plane[0].y;
897 u32 sprctl, linear_offset;
898 unsigned long irqflags;
900 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
902 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
904 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
907 intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
908 intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
910 intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
913 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
915 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
916 intel_de_write_fw(dev_priv, SPROFFSET(pipe),
917 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
919 intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
920 intel_de_write_fw(dev_priv, SPRTILEOFF(pipe),
921 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
925 * The control register self-arms if the plane was previously
926 * disabled. Try to make the plane enable atomic by writing
927 * the control register just before the surface register.
929 intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
930 intel_de_write_fw(dev_priv, SPRSURF(pipe),
931 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
933 ivb_sprite_update_gamma(plane_state);
935 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
939 ivb_sprite_disable_arm(struct intel_plane *plane,
940 const struct intel_crtc_state *crtc_state)
942 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
943 enum pipe pipe = plane->pipe;
944 unsigned long irqflags;
946 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
948 intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
949 /* Disable the scaler */
950 if (IS_IVYBRIDGE(dev_priv))
951 intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
952 intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
954 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
958 ivb_sprite_get_hw_state(struct intel_plane *plane,
961 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
962 enum intel_display_power_domain power_domain;
963 intel_wakeref_t wakeref;
966 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
967 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
971 ret = intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
975 intel_display_power_put(dev_priv, power_domain, wakeref);
980 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
981 const struct intel_plane_state *plane_state)
983 const struct drm_framebuffer *fb = plane_state->hw.fb;
984 unsigned int hscale, pixel_rate;
985 unsigned int limit, decimate;
988 * Note that crtc_state->pixel_rate accounts for both
989 * horizontal and vertical panel fitter downscaling factors.
990 * Pre-HSW bspec tells us to only consider the horizontal
991 * downscaling factor here. We ignore that and just consider
992 * both for simplicity.
994 pixel_rate = crtc_state->pixel_rate;
996 /* Horizontal downscaling limits the maximum pixel rate */
997 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
998 &plane_state->uapi.dst,
1000 hscale = max(hscale, 0x10000u);
1002 /* Decimation steps at 2x,4x,8x,16x */
1003 decimate = ilog2(hscale >> 16);
1004 hscale >>= decimate;
1006 /* Starting limit is 90% of cdclk */
1009 /* -10% per decimation step */
1013 if (!fb->format->is_yuv)
1017 * We should also do -10% if sprite scaling is enabled
1018 * on the other pipe, but we can't really check for that,
1022 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
1027 g4x_sprite_max_stride(struct intel_plane *plane,
1028 u32 pixel_format, u64 modifier,
1029 unsigned int rotation)
1031 const struct drm_format_info *info = drm_format_info(pixel_format);
1032 int cpp = info->cpp[0];
1034 /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
1035 if (modifier == I915_FORMAT_MOD_X_TILED)
1036 return min(4096 * cpp, 16 * 1024);
1042 hsw_sprite_max_stride(struct intel_plane *plane,
1043 u32 pixel_format, u64 modifier,
1044 unsigned int rotation)
1046 const struct drm_format_info *info = drm_format_info(pixel_format);
1047 int cpp = info->cpp[0];
1049 /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
1050 return min(8192 * cpp, 16 * 1024);
1053 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1057 if (crtc_state->gamma_enable)
1058 dvscntr |= DVS_PIPE_GAMMA_ENABLE;
1060 if (crtc_state->csc_enable)
1061 dvscntr |= DVS_PIPE_CSC_ENABLE;
1066 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1067 const struct intel_plane_state *plane_state)
1069 struct drm_i915_private *dev_priv =
1070 to_i915(plane_state->uapi.plane->dev);
1071 const struct drm_framebuffer *fb = plane_state->hw.fb;
1072 unsigned int rotation = plane_state->hw.rotation;
1073 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1076 dvscntr = DVS_ENABLE;
1078 if (IS_SANDYBRIDGE(dev_priv))
1079 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1081 switch (fb->format->format) {
1082 case DRM_FORMAT_XBGR8888:
1083 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1085 case DRM_FORMAT_XRGB8888:
1086 dvscntr |= DVS_FORMAT_RGBX888;
1088 case DRM_FORMAT_XBGR2101010:
1089 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1091 case DRM_FORMAT_XRGB2101010:
1092 dvscntr |= DVS_FORMAT_RGBX101010;
1094 case DRM_FORMAT_XBGR16161616F:
1095 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1097 case DRM_FORMAT_XRGB16161616F:
1098 dvscntr |= DVS_FORMAT_RGBX161616;
1100 case DRM_FORMAT_YUYV:
1101 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1103 case DRM_FORMAT_YVYU:
1104 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1106 case DRM_FORMAT_UYVY:
1107 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1109 case DRM_FORMAT_VYUY:
1110 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1113 MISSING_CASE(fb->format->format);
1117 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1118 dvscntr |= DVS_YUV_FORMAT_BT709;
1120 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1121 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1123 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1124 dvscntr |= DVS_TILED;
1126 if (rotation & DRM_MODE_ROTATE_180)
1127 dvscntr |= DVS_ROTATE_180;
1129 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1130 dvscntr |= DVS_DEST_KEY;
1131 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1132 dvscntr |= DVS_SOURCE_KEY;
1137 static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state)
1139 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1140 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1141 const struct drm_framebuffer *fb = plane_state->hw.fb;
1142 enum pipe pipe = plane->pipe;
1146 /* Seems RGB data bypasses the gamma always */
1147 if (!fb->format->is_yuv)
1150 i9xx_plane_linear_gamma(gamma);
1152 /* FIXME these register are single buffered :( */
1153 /* The two end points are implicit (0.0 and 1.0) */
1154 for (i = 1; i < 8 - 1; i++)
1155 intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1156 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1159 static void ilk_sprite_linear_gamma(u16 gamma[17])
1163 for (i = 0; i < 17; i++)
1164 gamma[i] = (i << 10) / 16;
1167 static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state)
1169 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1170 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1171 const struct drm_framebuffer *fb = plane_state->hw.fb;
1172 enum pipe pipe = plane->pipe;
1176 /* Seems RGB data bypasses the gamma always */
1177 if (!fb->format->is_yuv)
1180 ilk_sprite_linear_gamma(gamma);
1182 /* FIXME these register are single buffered :( */
1183 for (i = 0; i < 16; i++)
1184 intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1185 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1187 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1188 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1189 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1194 g4x_sprite_update_noarm(struct intel_plane *plane,
1195 const struct intel_crtc_state *crtc_state,
1196 const struct intel_plane_state *plane_state)
1198 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1199 enum pipe pipe = plane->pipe;
1200 int crtc_x = plane_state->uapi.dst.x1;
1201 int crtc_y = plane_state->uapi.dst.y1;
1202 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1203 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1204 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1205 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1207 unsigned long irqflags;
1209 if (crtc_w != src_w || crtc_h != src_h)
1210 dvsscale = DVS_SCALE_ENABLE |
1211 DVS_SRC_WIDTH(src_w - 1) |
1212 DVS_SRC_HEIGHT(src_h - 1);
1214 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1216 intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1217 plane_state->view.color_plane[0].mapping_stride);
1218 intel_de_write_fw(dev_priv, DVSPOS(pipe),
1219 DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
1220 intel_de_write_fw(dev_priv, DVSSIZE(pipe),
1221 DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
1222 intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1224 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1228 g4x_sprite_update_arm(struct intel_plane *plane,
1229 const struct intel_crtc_state *crtc_state,
1230 const struct intel_plane_state *plane_state)
1232 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1233 enum pipe pipe = plane->pipe;
1234 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1235 u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1236 u32 x = plane_state->view.color_plane[0].x;
1237 u32 y = plane_state->view.color_plane[0].y;
1238 u32 dvscntr, linear_offset;
1239 unsigned long irqflags;
1241 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1243 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1245 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1248 intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1249 intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1251 intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1254 intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1255 intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
1258 * The control register self-arms if the plane was previously
1259 * disabled. Try to make the plane enable atomic by writing
1260 * the control register just before the surface register.
1262 intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1263 intel_de_write_fw(dev_priv, DVSSURF(pipe),
1264 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1266 if (IS_G4X(dev_priv))
1267 g4x_sprite_update_gamma(plane_state);
1269 ilk_sprite_update_gamma(plane_state);
1271 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1275 g4x_sprite_disable_arm(struct intel_plane *plane,
1276 const struct intel_crtc_state *crtc_state)
1278 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1279 enum pipe pipe = plane->pipe;
1280 unsigned long irqflags;
1282 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1284 intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1285 /* Disable the scaler */
1286 intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1287 intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1289 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1293 g4x_sprite_get_hw_state(struct intel_plane *plane,
1296 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1297 enum intel_display_power_domain power_domain;
1298 intel_wakeref_t wakeref;
1301 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1302 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1306 ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1308 *pipe = plane->pipe;
1310 intel_display_power_put(dev_priv, power_domain, wakeref);
1315 static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1320 switch (fb->format->format) {
1322 case DRM_FORMAT_XRGB16161616F:
1323 case DRM_FORMAT_ARGB16161616F:
1324 case DRM_FORMAT_XBGR16161616F:
1325 case DRM_FORMAT_ABGR16161616F:
1333 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1334 struct intel_plane_state *plane_state)
1336 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1337 const struct drm_framebuffer *fb = plane_state->hw.fb;
1338 const struct drm_rect *src = &plane_state->uapi.src;
1339 const struct drm_rect *dst = &plane_state->uapi.dst;
1340 int src_x, src_w, src_h, crtc_w, crtc_h;
1341 const struct drm_display_mode *adjusted_mode =
1342 &crtc_state->hw.adjusted_mode;
1343 unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1344 unsigned int cpp = fb->format->cpp[0];
1345 unsigned int width_bytes;
1346 int min_width, min_height;
1348 crtc_w = drm_rect_width(dst);
1349 crtc_h = drm_rect_height(dst);
1351 src_x = src->x1 >> 16;
1352 src_w = drm_rect_width(src) >> 16;
1353 src_h = drm_rect_height(src) >> 16;
1355 if (src_w == crtc_w && src_h == crtc_h)
1360 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1362 drm_dbg_kms(&i915->drm, "Source height must be even with interlaced modes\n");
1370 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1372 if (src_w < min_width || src_h < min_height ||
1373 src_w > 2048 || src_h > 2048) {
1374 drm_dbg_kms(&i915->drm, "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1375 src_w, src_h, min_width, min_height, 2048, 2048);
1379 if (width_bytes > 4096) {
1380 drm_dbg_kms(&i915->drm, "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1385 if (stride > 4096) {
1386 drm_dbg_kms(&i915->drm, "Stride (%u) exceeds hardware max with scaling (%u)\n",
1395 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1396 struct intel_plane_state *plane_state)
1398 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1399 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1400 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1401 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1404 if (g4x_fb_scalable(plane_state->hw.fb)) {
1405 if (DISPLAY_VER(dev_priv) < 7) {
1407 max_scale = 16 << 16;
1408 } else if (IS_IVYBRIDGE(dev_priv)) {
1410 max_scale = 2 << 16;
1414 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1415 min_scale, max_scale, true);
1419 ret = i9xx_check_plane_surface(plane_state);
1423 if (!plane_state->uapi.visible)
1426 ret = intel_plane_check_src_coordinates(plane_state);
1430 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1434 if (DISPLAY_VER(dev_priv) >= 7)
1435 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1437 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1442 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1444 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1445 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1446 unsigned int rotation = plane_state->hw.rotation;
1448 /* CHV ignores the mirror bit when the rotate bit is set :( */
1449 if (IS_CHERRYVIEW(dev_priv) &&
1450 rotation & DRM_MODE_ROTATE_180 &&
1451 rotation & DRM_MODE_REFLECT_X) {
1452 drm_dbg_kms(&dev_priv->drm,
1453 "Cannot rotate and reflect at the same time\n");
1461 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1462 struct intel_plane_state *plane_state)
1466 ret = chv_plane_check_rotation(plane_state);
1470 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1471 DRM_PLANE_HELPER_NO_SCALING,
1472 DRM_PLANE_HELPER_NO_SCALING,
1477 ret = i9xx_check_plane_surface(plane_state);
1481 if (!plane_state->uapi.visible)
1484 ret = intel_plane_check_src_coordinates(plane_state);
1488 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1493 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1495 return DISPLAY_VER(dev_priv) >= 9;
1498 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1499 const struct drm_intel_sprite_colorkey *set)
1501 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1502 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1503 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1508 * We want src key enabled on the
1509 * sprite and not on the primary.
1511 if (plane->id == PLANE_PRIMARY &&
1512 set->flags & I915_SET_COLORKEY_SOURCE)
1516 * On SKL+ we want dst key enabled on
1517 * the primary and not on the sprite.
1519 if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1520 set->flags & I915_SET_COLORKEY_DESTINATION)
1524 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1525 struct drm_file *file_priv)
1527 struct drm_i915_private *dev_priv = to_i915(dev);
1528 struct drm_intel_sprite_colorkey *set = data;
1529 struct drm_plane *plane;
1530 struct drm_plane_state *plane_state;
1531 struct drm_atomic_state *state;
1532 struct drm_modeset_acquire_ctx ctx;
1535 /* ignore the pointless "none" flag */
1536 set->flags &= ~I915_SET_COLORKEY_NONE;
1538 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1541 /* Make sure we don't try to enable both src & dest simultaneously */
1542 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1545 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1546 set->flags & I915_SET_COLORKEY_DESTINATION)
1549 plane = drm_plane_find(dev, file_priv, set->plane_id);
1550 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1554 * SKL+ only plane 2 can do destination keying against plane 1.
1555 * Also multiple planes can't do destination keying on the same
1556 * pipe simultaneously.
1558 if (DISPLAY_VER(dev_priv) >= 9 &&
1559 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1560 set->flags & I915_SET_COLORKEY_DESTINATION)
1563 drm_modeset_acquire_init(&ctx, 0);
1565 state = drm_atomic_state_alloc(plane->dev);
1570 state->acquire_ctx = &ctx;
1573 plane_state = drm_atomic_get_plane_state(state, plane);
1574 ret = PTR_ERR_OR_ZERO(plane_state);
1576 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1579 * On some platforms we have to configure
1580 * the dst colorkey on the primary plane.
1582 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1583 struct intel_crtc *crtc =
1584 intel_crtc_for_pipe(dev_priv,
1585 to_intel_plane(plane)->pipe);
1587 plane_state = drm_atomic_get_plane_state(state,
1588 crtc->base.primary);
1589 ret = PTR_ERR_OR_ZERO(plane_state);
1591 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1595 ret = drm_atomic_commit(state);
1597 if (ret != -EDEADLK)
1600 drm_atomic_state_clear(state);
1601 drm_modeset_backoff(&ctx);
1604 drm_atomic_state_put(state);
1606 drm_modeset_drop_locks(&ctx);
1607 drm_modeset_acquire_fini(&ctx);
1611 static const u32 g4x_sprite_formats[] = {
1612 DRM_FORMAT_XRGB8888,
1619 static const u32 snb_sprite_formats[] = {
1620 DRM_FORMAT_XRGB8888,
1621 DRM_FORMAT_XBGR8888,
1622 DRM_FORMAT_XRGB2101010,
1623 DRM_FORMAT_XBGR2101010,
1624 DRM_FORMAT_XRGB16161616F,
1625 DRM_FORMAT_XBGR16161616F,
1632 static const u32 vlv_sprite_formats[] = {
1635 DRM_FORMAT_XRGB8888,
1636 DRM_FORMAT_XBGR8888,
1637 DRM_FORMAT_ARGB8888,
1638 DRM_FORMAT_ABGR8888,
1639 DRM_FORMAT_XBGR2101010,
1640 DRM_FORMAT_ABGR2101010,
1647 static const u32 chv_pipe_b_sprite_formats[] = {
1650 DRM_FORMAT_XRGB8888,
1651 DRM_FORMAT_XBGR8888,
1652 DRM_FORMAT_ARGB8888,
1653 DRM_FORMAT_ABGR8888,
1654 DRM_FORMAT_XRGB2101010,
1655 DRM_FORMAT_XBGR2101010,
1656 DRM_FORMAT_ARGB2101010,
1657 DRM_FORMAT_ABGR2101010,
1664 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1665 u32 format, u64 modifier)
1667 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1671 case DRM_FORMAT_XRGB8888:
1672 case DRM_FORMAT_YUYV:
1673 case DRM_FORMAT_YVYU:
1674 case DRM_FORMAT_UYVY:
1675 case DRM_FORMAT_VYUY:
1676 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1677 modifier == I915_FORMAT_MOD_X_TILED)
1685 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1686 u32 format, u64 modifier)
1688 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1692 case DRM_FORMAT_XRGB8888:
1693 case DRM_FORMAT_XBGR8888:
1694 case DRM_FORMAT_XRGB2101010:
1695 case DRM_FORMAT_XBGR2101010:
1696 case DRM_FORMAT_XRGB16161616F:
1697 case DRM_FORMAT_XBGR16161616F:
1698 case DRM_FORMAT_YUYV:
1699 case DRM_FORMAT_YVYU:
1700 case DRM_FORMAT_UYVY:
1701 case DRM_FORMAT_VYUY:
1702 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1703 modifier == I915_FORMAT_MOD_X_TILED)
1711 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1712 u32 format, u64 modifier)
1714 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1719 case DRM_FORMAT_RGB565:
1720 case DRM_FORMAT_ABGR8888:
1721 case DRM_FORMAT_ARGB8888:
1722 case DRM_FORMAT_XBGR8888:
1723 case DRM_FORMAT_XRGB8888:
1724 case DRM_FORMAT_XBGR2101010:
1725 case DRM_FORMAT_ABGR2101010:
1726 case DRM_FORMAT_XRGB2101010:
1727 case DRM_FORMAT_ARGB2101010:
1728 case DRM_FORMAT_YUYV:
1729 case DRM_FORMAT_YVYU:
1730 case DRM_FORMAT_UYVY:
1731 case DRM_FORMAT_VYUY:
1732 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1733 modifier == I915_FORMAT_MOD_X_TILED)
1741 static const struct drm_plane_funcs g4x_sprite_funcs = {
1742 .update_plane = drm_atomic_helper_update_plane,
1743 .disable_plane = drm_atomic_helper_disable_plane,
1744 .destroy = intel_plane_destroy,
1745 .atomic_duplicate_state = intel_plane_duplicate_state,
1746 .atomic_destroy_state = intel_plane_destroy_state,
1747 .format_mod_supported = g4x_sprite_format_mod_supported,
1750 static const struct drm_plane_funcs snb_sprite_funcs = {
1751 .update_plane = drm_atomic_helper_update_plane,
1752 .disable_plane = drm_atomic_helper_disable_plane,
1753 .destroy = intel_plane_destroy,
1754 .atomic_duplicate_state = intel_plane_duplicate_state,
1755 .atomic_destroy_state = intel_plane_destroy_state,
1756 .format_mod_supported = snb_sprite_format_mod_supported,
1759 static const struct drm_plane_funcs vlv_sprite_funcs = {
1760 .update_plane = drm_atomic_helper_update_plane,
1761 .disable_plane = drm_atomic_helper_disable_plane,
1762 .destroy = intel_plane_destroy,
1763 .atomic_duplicate_state = intel_plane_duplicate_state,
1764 .atomic_destroy_state = intel_plane_destroy_state,
1765 .format_mod_supported = vlv_sprite_format_mod_supported,
1768 struct intel_plane *
1769 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1770 enum pipe pipe, int sprite)
1772 struct intel_plane *plane;
1773 const struct drm_plane_funcs *plane_funcs;
1774 unsigned int supported_rotations;
1775 const u64 *modifiers;
1780 plane = intel_plane_alloc();
1784 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1785 plane->update_noarm = vlv_sprite_update_noarm;
1786 plane->update_arm = vlv_sprite_update_arm;
1787 plane->disable_arm = vlv_sprite_disable_arm;
1788 plane->get_hw_state = vlv_sprite_get_hw_state;
1789 plane->check_plane = vlv_sprite_check;
1790 plane->max_stride = i965_plane_max_stride;
1791 plane->min_cdclk = vlv_plane_min_cdclk;
1793 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1794 formats = chv_pipe_b_sprite_formats;
1795 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1797 formats = vlv_sprite_formats;
1798 num_formats = ARRAY_SIZE(vlv_sprite_formats);
1801 plane_funcs = &vlv_sprite_funcs;
1802 } else if (DISPLAY_VER(dev_priv) >= 7) {
1803 plane->update_noarm = ivb_sprite_update_noarm;
1804 plane->update_arm = ivb_sprite_update_arm;
1805 plane->disable_arm = ivb_sprite_disable_arm;
1806 plane->get_hw_state = ivb_sprite_get_hw_state;
1807 plane->check_plane = g4x_sprite_check;
1809 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1810 plane->max_stride = hsw_sprite_max_stride;
1811 plane->min_cdclk = hsw_plane_min_cdclk;
1813 plane->max_stride = g4x_sprite_max_stride;
1814 plane->min_cdclk = ivb_sprite_min_cdclk;
1817 formats = snb_sprite_formats;
1818 num_formats = ARRAY_SIZE(snb_sprite_formats);
1820 plane_funcs = &snb_sprite_funcs;
1822 plane->update_noarm = g4x_sprite_update_noarm;
1823 plane->update_arm = g4x_sprite_update_arm;
1824 plane->disable_arm = g4x_sprite_disable_arm;
1825 plane->get_hw_state = g4x_sprite_get_hw_state;
1826 plane->check_plane = g4x_sprite_check;
1827 plane->max_stride = g4x_sprite_max_stride;
1828 plane->min_cdclk = g4x_sprite_min_cdclk;
1830 if (IS_SANDYBRIDGE(dev_priv)) {
1831 formats = snb_sprite_formats;
1832 num_formats = ARRAY_SIZE(snb_sprite_formats);
1834 plane_funcs = &snb_sprite_funcs;
1836 formats = g4x_sprite_formats;
1837 num_formats = ARRAY_SIZE(g4x_sprite_formats);
1839 plane_funcs = &g4x_sprite_funcs;
1843 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1844 supported_rotations =
1845 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1848 supported_rotations =
1849 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1853 plane->id = PLANE_SPRITE0 + sprite;
1854 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1856 modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1858 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1860 formats, num_formats, modifiers,
1861 DRM_PLANE_TYPE_OVERLAY,
1862 "sprite %c", sprite_name(pipe, sprite));
1868 drm_plane_create_rotation_property(&plane->base,
1870 supported_rotations);
1872 drm_plane_create_color_properties(&plane->base,
1873 BIT(DRM_COLOR_YCBCR_BT601) |
1874 BIT(DRM_COLOR_YCBCR_BT709),
1875 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1876 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1877 DRM_COLOR_YCBCR_BT709,
1878 DRM_COLOR_YCBCR_LIMITED_RANGE);
1881 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1883 intel_plane_helper_add(plane);
1888 intel_plane_free(plane);
1890 return ERR_PTR(ret);