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
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 <linux/string_helpers.h>
35 #include <drm/drm_atomic_helper.h>
36 #include <drm/drm_blend.h>
37 #include <drm/drm_color_mgmt.h>
38 #include <drm/drm_fourcc.h>
39 #include <drm/drm_rect.h>
42 #include "i9xx_plane.h"
43 #include "intel_atomic_plane.h"
45 #include "intel_display_types.h"
47 #include "intel_frontbuffer.h"
48 #include "intel_sprite.h"
49 #include "intel_sprite_regs.h"
51 static char sprite_name(struct intel_display *display, enum pipe pipe, int sprite)
53 return pipe * DISPLAY_RUNTIME_INFO(display)->num_sprites[pipe] + sprite + 'A';
56 static void i9xx_plane_linear_gamma(u16 gamma[8])
58 /* The points are not evenly spaced. */
59 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
62 for (i = 0; i < 8; i++)
63 gamma[i] = (in[i] << 8) / 32;
67 chv_sprite_update_csc(const struct intel_plane_state *plane_state)
69 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
70 struct intel_display *display = to_intel_display(plane->base.dev);
71 const struct drm_framebuffer *fb = plane_state->hw.fb;
72 enum plane_id plane_id = plane->id;
74 * |r| | c0 c1 c2 | |cr|
75 * |g| = | c3 c4 c5 | x |y |
76 * |b| | c6 c7 c8 | |cb|
78 * Coefficients are s3.12.
80 * Cb and Cr apparently come in as signed already, and
81 * we always get full range data in on account of CLRC0/1.
83 static const s16 csc_matrix[][9] = {
84 /* BT.601 full range YCbCr -> full range RGB */
85 [DRM_COLOR_YCBCR_BT601] = {
90 /* BT.709 full range YCbCr -> full range RGB */
91 [DRM_COLOR_YCBCR_BT709] = {
97 const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
99 /* Seems RGB data bypasses the CSC always */
100 if (!fb->format->is_yuv)
103 intel_de_write_fw(display, SPCSCYGOFF(plane_id),
104 SPCSC_OOFF(0) | SPCSC_IOFF(0));
105 intel_de_write_fw(display, SPCSCCBOFF(plane_id),
106 SPCSC_OOFF(0) | SPCSC_IOFF(0));
107 intel_de_write_fw(display, SPCSCCROFF(plane_id),
108 SPCSC_OOFF(0) | SPCSC_IOFF(0));
110 intel_de_write_fw(display, SPCSCC01(plane_id),
111 SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
112 intel_de_write_fw(display, SPCSCC23(plane_id),
113 SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
114 intel_de_write_fw(display, SPCSCC45(plane_id),
115 SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
116 intel_de_write_fw(display, SPCSCC67(plane_id),
117 SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
118 intel_de_write_fw(display, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
120 intel_de_write_fw(display, SPCSCYGICLAMP(plane_id),
121 SPCSC_IMAX(1023) | SPCSC_IMIN(0));
122 intel_de_write_fw(display, SPCSCCBICLAMP(plane_id),
123 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
124 intel_de_write_fw(display, SPCSCCRICLAMP(plane_id),
125 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
127 intel_de_write_fw(display, SPCSCYGOCLAMP(plane_id),
128 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
129 intel_de_write_fw(display, SPCSCCBOCLAMP(plane_id),
130 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
131 intel_de_write_fw(display, SPCSCCROCLAMP(plane_id),
132 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
139 vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
141 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
142 struct intel_display *display = to_intel_display(plane->base.dev);
143 const struct drm_framebuffer *fb = plane_state->hw.fb;
144 enum pipe pipe = plane->pipe;
145 enum plane_id plane_id = plane->id;
146 int contrast, brightness, sh_scale, sh_sin, sh_cos;
148 if (fb->format->is_yuv &&
149 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
151 * Expand limited range to full range:
152 * Contrast is applied first and is used to expand Y range.
153 * Brightness is applied second and is used to remove the
154 * offset from Y. Saturation/hue is used to expand CbCr range.
156 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
157 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
158 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
159 sh_sin = SIN_0 * sh_scale;
160 sh_cos = COS_0 * sh_scale;
162 /* Pass-through everything. */
166 sh_sin = SIN_0 * sh_scale;
167 sh_cos = COS_0 * sh_scale;
170 /* FIXME these register are single buffered :( */
171 intel_de_write_fw(display, SPCLRC0(pipe, plane_id),
172 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
173 intel_de_write_fw(display, SPCLRC1(pipe, plane_id),
174 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
178 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
179 const struct intel_plane_state *plane_state,
180 unsigned int *num, unsigned int *den)
182 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
183 const struct drm_framebuffer *fb = plane_state->hw.fb;
184 unsigned int cpp = fb->format->cpp[0];
187 * VLV bspec only considers cases where all three planes are
188 * enabled, and cases where the primary and one sprite is enabled.
189 * Let's assume the case with just two sprites enabled also
190 * maps to the latter case.
192 if (hweight8(active_planes) == 3) {
207 } else if (hweight8(active_planes) == 2) {
236 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
237 const struct intel_plane_state *plane_state)
239 unsigned int pixel_rate;
240 unsigned int num, den;
243 * Note that crtc_state->pixel_rate accounts for both
244 * horizontal and vertical panel fitter downscaling factors.
245 * Pre-HSW bspec tells us to only consider the horizontal
246 * downscaling factor here. We ignore that and just consider
247 * both for simplicity.
249 pixel_rate = crtc_state->pixel_rate;
251 vlv_plane_ratio(crtc_state, plane_state, &num, &den);
253 return DIV_ROUND_UP(pixel_rate * num, den);
256 static unsigned int vlv_sprite_min_alignment(struct intel_plane *plane,
257 const struct drm_framebuffer *fb,
260 switch (fb->modifier) {
261 case I915_FORMAT_MOD_X_TILED:
263 case DRM_FORMAT_MOD_LINEAR:
266 MISSING_CASE(fb->modifier);
271 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
275 if (crtc_state->gamma_enable)
276 sprctl |= SP_PIPE_GAMMA_ENABLE;
281 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
282 const struct intel_plane_state *plane_state)
284 const struct drm_framebuffer *fb = plane_state->hw.fb;
285 unsigned int rotation = plane_state->hw.rotation;
286 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
291 switch (fb->format->format) {
292 case DRM_FORMAT_YUYV:
293 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
295 case DRM_FORMAT_YVYU:
296 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
298 case DRM_FORMAT_UYVY:
299 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
301 case DRM_FORMAT_VYUY:
302 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
305 sprctl |= SP_FORMAT_8BPP;
307 case DRM_FORMAT_RGB565:
308 sprctl |= SP_FORMAT_BGR565;
310 case DRM_FORMAT_XRGB8888:
311 sprctl |= SP_FORMAT_BGRX8888;
313 case DRM_FORMAT_ARGB8888:
314 sprctl |= SP_FORMAT_BGRA8888;
316 case DRM_FORMAT_XBGR2101010:
317 sprctl |= SP_FORMAT_RGBX1010102;
319 case DRM_FORMAT_ABGR2101010:
320 sprctl |= SP_FORMAT_RGBA1010102;
322 case DRM_FORMAT_XRGB2101010:
323 sprctl |= SP_FORMAT_BGRX1010102;
325 case DRM_FORMAT_ARGB2101010:
326 sprctl |= SP_FORMAT_BGRA1010102;
328 case DRM_FORMAT_XBGR8888:
329 sprctl |= SP_FORMAT_RGBX8888;
331 case DRM_FORMAT_ABGR8888:
332 sprctl |= SP_FORMAT_RGBA8888;
335 MISSING_CASE(fb->format->format);
339 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
340 sprctl |= SP_YUV_FORMAT_BT709;
342 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
345 if (rotation & DRM_MODE_ROTATE_180)
346 sprctl |= SP_ROTATE_180;
348 if (rotation & DRM_MODE_REFLECT_X)
351 if (key->flags & I915_SET_COLORKEY_SOURCE)
352 sprctl |= SP_SOURCE_KEY;
357 static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
359 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
360 struct intel_display *display = to_intel_display(plane->base.dev);
361 const struct drm_framebuffer *fb = plane_state->hw.fb;
362 enum pipe pipe = plane->pipe;
363 enum plane_id plane_id = plane->id;
367 /* Seems RGB data bypasses the gamma always */
368 if (!fb->format->is_yuv)
371 i9xx_plane_linear_gamma(gamma);
373 /* FIXME these register are single buffered :( */
374 /* The two end points are implicit (0.0 and 1.0) */
375 for (i = 1; i < 8 - 1; i++)
376 intel_de_write_fw(display, SPGAMC(pipe, plane_id, i - 1),
377 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
381 vlv_sprite_update_noarm(struct intel_dsb *dsb,
382 struct intel_plane *plane,
383 const struct intel_crtc_state *crtc_state,
384 const struct intel_plane_state *plane_state)
386 struct intel_display *display = to_intel_display(plane->base.dev);
387 enum pipe pipe = plane->pipe;
388 enum plane_id plane_id = plane->id;
389 int crtc_x = plane_state->uapi.dst.x1;
390 int crtc_y = plane_state->uapi.dst.y1;
391 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
392 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
394 intel_de_write_fw(display, SPSTRIDE(pipe, plane_id),
395 plane_state->view.color_plane[0].mapping_stride);
396 intel_de_write_fw(display, SPPOS(pipe, plane_id),
397 SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
398 intel_de_write_fw(display, SPSIZE(pipe, plane_id),
399 SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
403 vlv_sprite_update_arm(struct intel_dsb *dsb,
404 struct intel_plane *plane,
405 const struct intel_crtc_state *crtc_state,
406 const struct intel_plane_state *plane_state)
408 struct intel_display *display = to_intel_display(plane->base.dev);
409 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
410 enum pipe pipe = plane->pipe;
411 enum plane_id plane_id = plane->id;
412 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
413 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
414 u32 x = plane_state->view.color_plane[0].x;
415 u32 y = plane_state->view.color_plane[0].y;
416 u32 sprctl, linear_offset;
418 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
420 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
422 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
423 chv_sprite_update_csc(plane_state);
426 intel_de_write_fw(display, SPKEYMINVAL(pipe, plane_id),
428 intel_de_write_fw(display, SPKEYMSK(pipe, plane_id),
430 intel_de_write_fw(display, SPKEYMAXVAL(pipe, plane_id),
434 intel_de_write_fw(display, SPCONSTALPHA(pipe, plane_id), 0);
436 intel_de_write_fw(display, SPLINOFF(pipe, plane_id), linear_offset);
437 intel_de_write_fw(display, SPTILEOFF(pipe, plane_id),
438 SP_OFFSET_Y(y) | SP_OFFSET_X(x));
441 * The control register self-arms if the plane was previously
442 * disabled. Try to make the plane enable atomic by writing
443 * the control register just before the surface register.
445 intel_de_write_fw(display, SPCNTR(pipe, plane_id), sprctl);
446 intel_de_write_fw(display, SPSURF(pipe, plane_id),
447 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
449 vlv_sprite_update_clrc(plane_state);
450 vlv_sprite_update_gamma(plane_state);
454 vlv_sprite_disable_arm(struct intel_dsb *dsb,
455 struct intel_plane *plane,
456 const struct intel_crtc_state *crtc_state)
458 struct intel_display *display = to_intel_display(plane->base.dev);
459 enum pipe pipe = plane->pipe;
460 enum plane_id plane_id = plane->id;
462 intel_de_write_fw(display, SPCNTR(pipe, plane_id), 0);
463 intel_de_write_fw(display, SPSURF(pipe, plane_id), 0);
467 vlv_sprite_get_hw_state(struct intel_plane *plane,
470 struct intel_display *display = to_intel_display(plane->base.dev);
471 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
472 enum intel_display_power_domain power_domain;
473 enum plane_id plane_id = plane->id;
474 intel_wakeref_t wakeref;
477 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
478 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
482 ret = intel_de_read(display, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
486 intel_display_power_put(dev_priv, power_domain, wakeref);
491 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
492 const struct intel_plane_state *plane_state,
493 unsigned int *num, unsigned int *den)
495 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
496 const struct drm_framebuffer *fb = plane_state->hw.fb;
497 unsigned int cpp = fb->format->cpp[0];
499 if (hweight8(active_planes) == 2) {
528 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
529 const struct intel_plane_state *plane_state,
530 unsigned int *num, unsigned int *den)
532 const struct drm_framebuffer *fb = plane_state->hw.fb;
533 unsigned int cpp = fb->format->cpp[0];
555 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
556 const struct intel_plane_state *plane_state)
558 unsigned int pixel_rate;
559 unsigned int num, den;
562 * Note that crtc_state->pixel_rate accounts for both
563 * horizontal and vertical panel fitter downscaling factors.
564 * Pre-HSW bspec tells us to only consider the horizontal
565 * downscaling factor here. We ignore that and just consider
566 * both for simplicity.
568 pixel_rate = crtc_state->pixel_rate;
570 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
572 return DIV_ROUND_UP(pixel_rate * num, den);
575 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
576 const struct intel_plane_state *plane_state)
578 unsigned int src_w, dst_w, pixel_rate;
579 unsigned int num, den;
582 * Note that crtc_state->pixel_rate accounts for both
583 * horizontal and vertical panel fitter downscaling factors.
584 * Pre-HSW bspec tells us to only consider the horizontal
585 * downscaling factor here. We ignore that and just consider
586 * both for simplicity.
588 pixel_rate = crtc_state->pixel_rate;
590 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
591 dst_w = drm_rect_width(&plane_state->uapi.dst);
594 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
596 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
598 /* Horizontal downscaling limits the maximum pixel rate */
599 dst_w = min(src_w, dst_w);
601 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
605 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
606 const struct intel_plane_state *plane_state,
607 unsigned int *num, unsigned int *den)
609 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
610 const struct drm_framebuffer *fb = plane_state->hw.fb;
611 unsigned int cpp = fb->format->cpp[0];
613 if (hweight8(active_planes) == 2) {
638 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
639 const struct intel_plane_state *plane_state)
641 unsigned int pixel_rate = crtc_state->pixel_rate;
642 unsigned int num, den;
644 hsw_plane_ratio(crtc_state, plane_state, &num, &den);
646 return DIV_ROUND_UP(pixel_rate * num, den);
649 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
653 if (crtc_state->gamma_enable)
654 sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
656 if (crtc_state->csc_enable)
657 sprctl |= SPRITE_PIPE_CSC_ENABLE;
662 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
664 struct drm_i915_private *dev_priv =
665 to_i915(plane_state->uapi.plane->dev);
666 const struct drm_framebuffer *fb = plane_state->hw.fb;
668 return fb->format->cpp[0] == 8 &&
669 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
672 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
673 const struct intel_plane_state *plane_state)
675 struct drm_i915_private *dev_priv =
676 to_i915(plane_state->uapi.plane->dev);
677 const struct drm_framebuffer *fb = plane_state->hw.fb;
678 unsigned int rotation = plane_state->hw.rotation;
679 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
682 sprctl = SPRITE_ENABLE;
684 if (IS_IVYBRIDGE(dev_priv))
685 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
687 switch (fb->format->format) {
688 case DRM_FORMAT_XBGR8888:
689 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
691 case DRM_FORMAT_XRGB8888:
692 sprctl |= SPRITE_FORMAT_RGBX888;
694 case DRM_FORMAT_XBGR2101010:
695 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
697 case DRM_FORMAT_XRGB2101010:
698 sprctl |= SPRITE_FORMAT_RGBX101010;
700 case DRM_FORMAT_XBGR16161616F:
701 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
703 case DRM_FORMAT_XRGB16161616F:
704 sprctl |= SPRITE_FORMAT_RGBX161616;
706 case DRM_FORMAT_YUYV:
707 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
709 case DRM_FORMAT_YVYU:
710 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
712 case DRM_FORMAT_UYVY:
713 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
715 case DRM_FORMAT_VYUY:
716 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
719 MISSING_CASE(fb->format->format);
723 if (!ivb_need_sprite_gamma(plane_state))
724 sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
726 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
727 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
729 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
730 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
732 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
733 sprctl |= SPRITE_TILED;
735 if (rotation & DRM_MODE_ROTATE_180)
736 sprctl |= SPRITE_ROTATE_180;
738 if (key->flags & I915_SET_COLORKEY_DESTINATION)
739 sprctl |= SPRITE_DEST_KEY;
740 else if (key->flags & I915_SET_COLORKEY_SOURCE)
741 sprctl |= SPRITE_SOURCE_KEY;
746 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
752 * WaFP16GammaEnabling:ivb,hsw
753 * "Workaround : When using the 64-bit format, the sprite output
754 * on each color channel has one quarter amplitude. It can be
755 * brought up to full amplitude by using sprite internal gamma
756 * correction, pipe gamma correction, or pipe color space
757 * conversion to multiply the sprite output by four."
761 for (i = 0; i < 16; i++)
762 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
764 gamma[i] = min((scale * i << 10) / 16, 1 << 10);
771 static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
773 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
774 struct intel_display *display = to_intel_display(plane->base.dev);
775 enum pipe pipe = plane->pipe;
779 if (!ivb_need_sprite_gamma(plane_state))
782 ivb_sprite_linear_gamma(plane_state, gamma);
784 /* FIXME these register are single buffered :( */
785 for (i = 0; i < 16; i++)
786 intel_de_write_fw(display, SPRGAMC(pipe, i),
787 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
789 intel_de_write_fw(display, SPRGAMC16(pipe, 0), gamma[i]);
790 intel_de_write_fw(display, SPRGAMC16(pipe, 1), gamma[i]);
791 intel_de_write_fw(display, SPRGAMC16(pipe, 2), gamma[i]);
794 intel_de_write_fw(display, SPRGAMC17(pipe, 0), gamma[i]);
795 intel_de_write_fw(display, SPRGAMC17(pipe, 1), gamma[i]);
796 intel_de_write_fw(display, SPRGAMC17(pipe, 2), gamma[i]);
801 ivb_sprite_update_noarm(struct intel_dsb *dsb,
802 struct intel_plane *plane,
803 const struct intel_crtc_state *crtc_state,
804 const struct intel_plane_state *plane_state)
806 struct intel_display *display = to_intel_display(plane->base.dev);
807 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
808 enum pipe pipe = plane->pipe;
809 int crtc_x = plane_state->uapi.dst.x1;
810 int crtc_y = plane_state->uapi.dst.y1;
811 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
812 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
813 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
814 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
817 if (crtc_w != src_w || crtc_h != src_h)
818 sprscale = SPRITE_SCALE_ENABLE |
819 SPRITE_SRC_WIDTH(src_w - 1) |
820 SPRITE_SRC_HEIGHT(src_h - 1);
822 intel_de_write_fw(display, SPRSTRIDE(pipe),
823 plane_state->view.color_plane[0].mapping_stride);
824 intel_de_write_fw(display, SPRPOS(pipe),
825 SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
826 intel_de_write_fw(display, SPRSIZE(pipe),
827 SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
828 if (IS_IVYBRIDGE(dev_priv))
829 intel_de_write_fw(display, SPRSCALE(pipe), sprscale);
833 ivb_sprite_update_arm(struct intel_dsb *dsb,
834 struct intel_plane *plane,
835 const struct intel_crtc_state *crtc_state,
836 const struct intel_plane_state *plane_state)
838 struct intel_display *display = to_intel_display(plane->base.dev);
839 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
840 enum pipe pipe = plane->pipe;
841 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
842 u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
843 u32 x = plane_state->view.color_plane[0].x;
844 u32 y = plane_state->view.color_plane[0].y;
845 u32 sprctl, linear_offset;
847 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
849 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
852 intel_de_write_fw(display, SPRKEYVAL(pipe), key->min_value);
853 intel_de_write_fw(display, SPRKEYMSK(pipe),
855 intel_de_write_fw(display, SPRKEYMAX(pipe), key->max_value);
858 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
860 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
861 intel_de_write_fw(display, SPROFFSET(pipe),
862 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
864 intel_de_write_fw(display, SPRLINOFF(pipe), linear_offset);
865 intel_de_write_fw(display, SPRTILEOFF(pipe),
866 SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
870 * The control register self-arms if the plane was previously
871 * disabled. Try to make the plane enable atomic by writing
872 * the control register just before the surface register.
874 intel_de_write_fw(display, SPRCTL(pipe), sprctl);
875 intel_de_write_fw(display, SPRSURF(pipe),
876 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
878 ivb_sprite_update_gamma(plane_state);
882 ivb_sprite_disable_arm(struct intel_dsb *dsb,
883 struct intel_plane *plane,
884 const struct intel_crtc_state *crtc_state)
886 struct intel_display *display = to_intel_display(plane->base.dev);
887 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
888 enum pipe pipe = plane->pipe;
890 intel_de_write_fw(display, SPRCTL(pipe), 0);
891 /* Disable the scaler */
892 if (IS_IVYBRIDGE(dev_priv))
893 intel_de_write_fw(display, SPRSCALE(pipe), 0);
894 intel_de_write_fw(display, SPRSURF(pipe), 0);
898 ivb_sprite_get_hw_state(struct intel_plane *plane,
901 struct intel_display *display = to_intel_display(plane->base.dev);
902 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
903 enum intel_display_power_domain power_domain;
904 intel_wakeref_t wakeref;
907 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
908 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
912 ret = intel_de_read(display, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
916 intel_display_power_put(dev_priv, power_domain, wakeref);
921 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
922 const struct intel_plane_state *plane_state)
924 const struct drm_framebuffer *fb = plane_state->hw.fb;
925 unsigned int hscale, pixel_rate;
926 unsigned int limit, decimate;
929 * Note that crtc_state->pixel_rate accounts for both
930 * horizontal and vertical panel fitter downscaling factors.
931 * Pre-HSW bspec tells us to only consider the horizontal
932 * downscaling factor here. We ignore that and just consider
933 * both for simplicity.
935 pixel_rate = crtc_state->pixel_rate;
937 /* Horizontal downscaling limits the maximum pixel rate */
938 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
939 &plane_state->uapi.dst,
941 hscale = max(hscale, 0x10000u);
943 /* Decimation steps at 2x,4x,8x,16x */
944 decimate = ilog2(hscale >> 16);
947 /* Starting limit is 90% of cdclk */
950 /* -10% per decimation step */
954 if (!fb->format->is_yuv)
958 * We should also do -10% if sprite scaling is enabled
959 * on the other pipe, but we can't really check for that,
963 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
968 g4x_sprite_max_stride(struct intel_plane *plane,
969 u32 pixel_format, u64 modifier,
970 unsigned int rotation)
972 const struct drm_format_info *info = drm_format_info(pixel_format);
973 int cpp = info->cpp[0];
975 /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
976 if (modifier == I915_FORMAT_MOD_X_TILED)
977 return min(4096 * cpp, 16 * 1024);
983 hsw_sprite_max_stride(struct intel_plane *plane,
984 u32 pixel_format, u64 modifier,
985 unsigned int rotation)
987 const struct drm_format_info *info = drm_format_info(pixel_format);
988 int cpp = info->cpp[0];
990 /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
991 return min(8192 * cpp, 16 * 1024);
994 static unsigned int g4x_sprite_min_alignment(struct intel_plane *plane,
995 const struct drm_framebuffer *fb,
1001 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1005 if (crtc_state->gamma_enable)
1006 dvscntr |= DVS_PIPE_GAMMA_ENABLE;
1008 if (crtc_state->csc_enable)
1009 dvscntr |= DVS_PIPE_CSC_ENABLE;
1014 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1015 const struct intel_plane_state *plane_state)
1017 struct drm_i915_private *dev_priv =
1018 to_i915(plane_state->uapi.plane->dev);
1019 const struct drm_framebuffer *fb = plane_state->hw.fb;
1020 unsigned int rotation = plane_state->hw.rotation;
1021 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1024 dvscntr = DVS_ENABLE;
1026 if (IS_SANDYBRIDGE(dev_priv))
1027 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1029 switch (fb->format->format) {
1030 case DRM_FORMAT_XBGR8888:
1031 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1033 case DRM_FORMAT_XRGB8888:
1034 dvscntr |= DVS_FORMAT_RGBX888;
1036 case DRM_FORMAT_XBGR2101010:
1037 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1039 case DRM_FORMAT_XRGB2101010:
1040 dvscntr |= DVS_FORMAT_RGBX101010;
1042 case DRM_FORMAT_XBGR16161616F:
1043 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1045 case DRM_FORMAT_XRGB16161616F:
1046 dvscntr |= DVS_FORMAT_RGBX161616;
1048 case DRM_FORMAT_YUYV:
1049 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1051 case DRM_FORMAT_YVYU:
1052 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1054 case DRM_FORMAT_UYVY:
1055 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1057 case DRM_FORMAT_VYUY:
1058 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1061 MISSING_CASE(fb->format->format);
1065 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1066 dvscntr |= DVS_YUV_FORMAT_BT709;
1068 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1069 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1071 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1072 dvscntr |= DVS_TILED;
1074 if (rotation & DRM_MODE_ROTATE_180)
1075 dvscntr |= DVS_ROTATE_180;
1077 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1078 dvscntr |= DVS_DEST_KEY;
1079 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1080 dvscntr |= DVS_SOURCE_KEY;
1085 static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state)
1087 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1088 struct intel_display *display = to_intel_display(plane->base.dev);
1089 const struct drm_framebuffer *fb = plane_state->hw.fb;
1090 enum pipe pipe = plane->pipe;
1094 /* Seems RGB data bypasses the gamma always */
1095 if (!fb->format->is_yuv)
1098 i9xx_plane_linear_gamma(gamma);
1100 /* FIXME these register are single buffered :( */
1101 /* The two end points are implicit (0.0 and 1.0) */
1102 for (i = 1; i < 8 - 1; i++)
1103 intel_de_write_fw(display, DVSGAMC_G4X(pipe, i - 1),
1104 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1107 static void ilk_sprite_linear_gamma(u16 gamma[17])
1111 for (i = 0; i < 17; i++)
1112 gamma[i] = (i << 10) / 16;
1115 static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state)
1117 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1118 struct intel_display *display = to_intel_display(plane->base.dev);
1119 const struct drm_framebuffer *fb = plane_state->hw.fb;
1120 enum pipe pipe = plane->pipe;
1124 /* Seems RGB data bypasses the gamma always */
1125 if (!fb->format->is_yuv)
1128 ilk_sprite_linear_gamma(gamma);
1130 /* FIXME these register are single buffered :( */
1131 for (i = 0; i < 16; i++)
1132 intel_de_write_fw(display, DVSGAMC_ILK(pipe, i),
1133 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1135 intel_de_write_fw(display, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1136 intel_de_write_fw(display, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1137 intel_de_write_fw(display, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1142 g4x_sprite_update_noarm(struct intel_dsb *dsb,
1143 struct intel_plane *plane,
1144 const struct intel_crtc_state *crtc_state,
1145 const struct intel_plane_state *plane_state)
1147 struct intel_display *display = to_intel_display(plane->base.dev);
1148 enum pipe pipe = plane->pipe;
1149 int crtc_x = plane_state->uapi.dst.x1;
1150 int crtc_y = plane_state->uapi.dst.y1;
1151 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1152 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1153 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1154 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1157 if (crtc_w != src_w || crtc_h != src_h)
1158 dvsscale = DVS_SCALE_ENABLE |
1159 DVS_SRC_WIDTH(src_w - 1) |
1160 DVS_SRC_HEIGHT(src_h - 1);
1162 intel_de_write_fw(display, DVSSTRIDE(pipe),
1163 plane_state->view.color_plane[0].mapping_stride);
1164 intel_de_write_fw(display, DVSPOS(pipe),
1165 DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
1166 intel_de_write_fw(display, DVSSIZE(pipe),
1167 DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
1168 intel_de_write_fw(display, DVSSCALE(pipe), dvsscale);
1172 g4x_sprite_update_arm(struct intel_dsb *dsb,
1173 struct intel_plane *plane,
1174 const struct intel_crtc_state *crtc_state,
1175 const struct intel_plane_state *plane_state)
1177 struct intel_display *display = to_intel_display(plane->base.dev);
1178 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1179 enum pipe pipe = plane->pipe;
1180 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1181 u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1182 u32 x = plane_state->view.color_plane[0].x;
1183 u32 y = plane_state->view.color_plane[0].y;
1184 u32 dvscntr, linear_offset;
1186 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1188 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1191 intel_de_write_fw(display, DVSKEYVAL(pipe), key->min_value);
1192 intel_de_write_fw(display, DVSKEYMSK(pipe),
1194 intel_de_write_fw(display, DVSKEYMAX(pipe), key->max_value);
1197 intel_de_write_fw(display, DVSLINOFF(pipe), linear_offset);
1198 intel_de_write_fw(display, DVSTILEOFF(pipe),
1199 DVS_OFFSET_Y(y) | DVS_OFFSET_X(x));
1202 * The control register self-arms if the plane was previously
1203 * disabled. Try to make the plane enable atomic by writing
1204 * the control register just before the surface register.
1206 intel_de_write_fw(display, DVSCNTR(pipe), dvscntr);
1207 intel_de_write_fw(display, DVSSURF(pipe),
1208 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1210 if (IS_G4X(dev_priv))
1211 g4x_sprite_update_gamma(plane_state);
1213 ilk_sprite_update_gamma(plane_state);
1217 g4x_sprite_disable_arm(struct intel_dsb *dsb,
1218 struct intel_plane *plane,
1219 const struct intel_crtc_state *crtc_state)
1221 struct intel_display *display = to_intel_display(plane->base.dev);
1222 enum pipe pipe = plane->pipe;
1224 intel_de_write_fw(display, DVSCNTR(pipe), 0);
1225 /* Disable the scaler */
1226 intel_de_write_fw(display, DVSSCALE(pipe), 0);
1227 intel_de_write_fw(display, DVSSURF(pipe), 0);
1231 g4x_sprite_get_hw_state(struct intel_plane *plane,
1234 struct intel_display *display = to_intel_display(plane->base.dev);
1235 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1236 enum intel_display_power_domain power_domain;
1237 intel_wakeref_t wakeref;
1240 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1241 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1245 ret = intel_de_read(display, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1247 *pipe = plane->pipe;
1249 intel_display_power_put(dev_priv, power_domain, wakeref);
1254 static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1259 switch (fb->format->format) {
1261 case DRM_FORMAT_XRGB16161616F:
1262 case DRM_FORMAT_ARGB16161616F:
1263 case DRM_FORMAT_XBGR16161616F:
1264 case DRM_FORMAT_ABGR16161616F:
1272 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1273 struct intel_plane_state *plane_state)
1275 struct intel_display *display = to_intel_display(crtc_state);
1276 const struct drm_framebuffer *fb = plane_state->hw.fb;
1277 const struct drm_rect *src = &plane_state->uapi.src;
1278 const struct drm_rect *dst = &plane_state->uapi.dst;
1279 int src_x, src_w, src_h, crtc_w, crtc_h;
1280 const struct drm_display_mode *adjusted_mode =
1281 &crtc_state->hw.adjusted_mode;
1282 unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1283 unsigned int cpp = fb->format->cpp[0];
1284 unsigned int width_bytes;
1285 int min_width, min_height;
1287 crtc_w = drm_rect_width(dst);
1288 crtc_h = drm_rect_height(dst);
1290 src_x = src->x1 >> 16;
1291 src_w = drm_rect_width(src) >> 16;
1292 src_h = drm_rect_height(src) >> 16;
1294 if (src_w == crtc_w && src_h == crtc_h)
1299 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1301 drm_dbg_kms(display->drm,
1302 "Source height must be even with interlaced modes\n");
1310 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1312 if (src_w < min_width || src_h < min_height ||
1313 src_w > 2048 || src_h > 2048) {
1314 drm_dbg_kms(display->drm,
1315 "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1316 src_w, src_h, min_width, min_height, 2048, 2048);
1320 if (width_bytes > 4096) {
1321 drm_dbg_kms(display->drm,
1322 "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1327 if (stride > 4096) {
1328 drm_dbg_kms(display->drm,
1329 "Stride (%u) exceeds hardware max with scaling (%u)\n",
1338 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1339 struct intel_plane_state *plane_state)
1341 struct intel_display *display = to_intel_display(crtc_state);
1342 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1343 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1344 int min_scale = DRM_PLANE_NO_SCALING;
1345 int max_scale = DRM_PLANE_NO_SCALING;
1348 if (g4x_fb_scalable(plane_state->hw.fb)) {
1349 if (DISPLAY_VER(display) < 7) {
1351 max_scale = 16 << 16;
1352 } else if (IS_IVYBRIDGE(dev_priv)) {
1354 max_scale = 2 << 16;
1358 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1359 min_scale, max_scale, true);
1363 ret = i9xx_check_plane_surface(plane_state);
1367 if (!plane_state->uapi.visible)
1370 ret = intel_plane_check_src_coordinates(plane_state);
1374 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1378 if (DISPLAY_VER(display) >= 7)
1379 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1381 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1386 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1388 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1389 struct intel_display *display = to_intel_display(plane->base.dev);
1390 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1391 unsigned int rotation = plane_state->hw.rotation;
1393 /* CHV ignores the mirror bit when the rotate bit is set :( */
1394 if (IS_CHERRYVIEW(dev_priv) &&
1395 rotation & DRM_MODE_ROTATE_180 &&
1396 rotation & DRM_MODE_REFLECT_X) {
1397 drm_dbg_kms(display->drm,
1398 "Cannot rotate and reflect at the same time\n");
1406 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1407 struct intel_plane_state *plane_state)
1411 ret = chv_plane_check_rotation(plane_state);
1415 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1416 DRM_PLANE_NO_SCALING,
1417 DRM_PLANE_NO_SCALING,
1422 ret = i9xx_check_plane_surface(plane_state);
1426 if (!plane_state->uapi.visible)
1429 ret = intel_plane_check_src_coordinates(plane_state);
1433 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1438 static const u32 g4x_sprite_formats[] = {
1439 DRM_FORMAT_XRGB8888,
1446 static const u32 snb_sprite_formats[] = {
1447 DRM_FORMAT_XRGB8888,
1448 DRM_FORMAT_XBGR8888,
1449 DRM_FORMAT_XRGB2101010,
1450 DRM_FORMAT_XBGR2101010,
1451 DRM_FORMAT_XRGB16161616F,
1452 DRM_FORMAT_XBGR16161616F,
1459 static const u32 vlv_sprite_formats[] = {
1462 DRM_FORMAT_XRGB8888,
1463 DRM_FORMAT_XBGR8888,
1464 DRM_FORMAT_ARGB8888,
1465 DRM_FORMAT_ABGR8888,
1466 DRM_FORMAT_XBGR2101010,
1467 DRM_FORMAT_ABGR2101010,
1474 static const u32 chv_pipe_b_sprite_formats[] = {
1477 DRM_FORMAT_XRGB8888,
1478 DRM_FORMAT_XBGR8888,
1479 DRM_FORMAT_ARGB8888,
1480 DRM_FORMAT_ABGR8888,
1481 DRM_FORMAT_XRGB2101010,
1482 DRM_FORMAT_XBGR2101010,
1483 DRM_FORMAT_ARGB2101010,
1484 DRM_FORMAT_ABGR2101010,
1491 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1492 u32 format, u64 modifier)
1494 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1498 case DRM_FORMAT_XRGB8888:
1499 case DRM_FORMAT_YUYV:
1500 case DRM_FORMAT_YVYU:
1501 case DRM_FORMAT_UYVY:
1502 case DRM_FORMAT_VYUY:
1503 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1504 modifier == I915_FORMAT_MOD_X_TILED)
1512 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1513 u32 format, u64 modifier)
1515 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1519 case DRM_FORMAT_XRGB8888:
1520 case DRM_FORMAT_XBGR8888:
1521 case DRM_FORMAT_XRGB2101010:
1522 case DRM_FORMAT_XBGR2101010:
1523 case DRM_FORMAT_XRGB16161616F:
1524 case DRM_FORMAT_XBGR16161616F:
1525 case DRM_FORMAT_YUYV:
1526 case DRM_FORMAT_YVYU:
1527 case DRM_FORMAT_UYVY:
1528 case DRM_FORMAT_VYUY:
1529 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1530 modifier == I915_FORMAT_MOD_X_TILED)
1538 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1539 u32 format, u64 modifier)
1541 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1546 case DRM_FORMAT_RGB565:
1547 case DRM_FORMAT_ABGR8888:
1548 case DRM_FORMAT_ARGB8888:
1549 case DRM_FORMAT_XBGR8888:
1550 case DRM_FORMAT_XRGB8888:
1551 case DRM_FORMAT_XBGR2101010:
1552 case DRM_FORMAT_ABGR2101010:
1553 case DRM_FORMAT_XRGB2101010:
1554 case DRM_FORMAT_ARGB2101010:
1555 case DRM_FORMAT_YUYV:
1556 case DRM_FORMAT_YVYU:
1557 case DRM_FORMAT_UYVY:
1558 case DRM_FORMAT_VYUY:
1559 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1560 modifier == I915_FORMAT_MOD_X_TILED)
1568 static const struct drm_plane_funcs g4x_sprite_funcs = {
1569 .update_plane = drm_atomic_helper_update_plane,
1570 .disable_plane = drm_atomic_helper_disable_plane,
1571 .destroy = intel_plane_destroy,
1572 .atomic_duplicate_state = intel_plane_duplicate_state,
1573 .atomic_destroy_state = intel_plane_destroy_state,
1574 .format_mod_supported = g4x_sprite_format_mod_supported,
1577 static const struct drm_plane_funcs snb_sprite_funcs = {
1578 .update_plane = drm_atomic_helper_update_plane,
1579 .disable_plane = drm_atomic_helper_disable_plane,
1580 .destroy = intel_plane_destroy,
1581 .atomic_duplicate_state = intel_plane_duplicate_state,
1582 .atomic_destroy_state = intel_plane_destroy_state,
1583 .format_mod_supported = snb_sprite_format_mod_supported,
1586 static const struct drm_plane_funcs vlv_sprite_funcs = {
1587 .update_plane = drm_atomic_helper_update_plane,
1588 .disable_plane = drm_atomic_helper_disable_plane,
1589 .destroy = intel_plane_destroy,
1590 .atomic_duplicate_state = intel_plane_duplicate_state,
1591 .atomic_destroy_state = intel_plane_destroy_state,
1592 .format_mod_supported = vlv_sprite_format_mod_supported,
1595 struct intel_plane *
1596 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1597 enum pipe pipe, int sprite)
1599 struct intel_display *display = &dev_priv->display;
1600 struct intel_plane *plane;
1601 const struct drm_plane_funcs *plane_funcs;
1602 unsigned int supported_rotations;
1603 const u64 *modifiers;
1608 plane = intel_plane_alloc();
1612 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1613 plane->update_noarm = vlv_sprite_update_noarm;
1614 plane->update_arm = vlv_sprite_update_arm;
1615 plane->disable_arm = vlv_sprite_disable_arm;
1616 plane->get_hw_state = vlv_sprite_get_hw_state;
1617 plane->check_plane = vlv_sprite_check;
1618 plane->max_stride = i965_plane_max_stride;
1619 plane->min_alignment = vlv_sprite_min_alignment;
1620 plane->min_cdclk = vlv_plane_min_cdclk;
1622 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1623 formats = chv_pipe_b_sprite_formats;
1624 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1626 formats = vlv_sprite_formats;
1627 num_formats = ARRAY_SIZE(vlv_sprite_formats);
1630 plane_funcs = &vlv_sprite_funcs;
1631 } else if (DISPLAY_VER(display) >= 7) {
1632 plane->update_noarm = ivb_sprite_update_noarm;
1633 plane->update_arm = ivb_sprite_update_arm;
1634 plane->disable_arm = ivb_sprite_disable_arm;
1635 plane->get_hw_state = ivb_sprite_get_hw_state;
1636 plane->check_plane = g4x_sprite_check;
1638 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1639 plane->max_stride = hsw_sprite_max_stride;
1640 plane->min_cdclk = hsw_plane_min_cdclk;
1642 plane->max_stride = g4x_sprite_max_stride;
1643 plane->min_cdclk = ivb_sprite_min_cdclk;
1646 plane->min_alignment = g4x_sprite_min_alignment;
1648 formats = snb_sprite_formats;
1649 num_formats = ARRAY_SIZE(snb_sprite_formats);
1651 plane_funcs = &snb_sprite_funcs;
1653 plane->update_noarm = g4x_sprite_update_noarm;
1654 plane->update_arm = g4x_sprite_update_arm;
1655 plane->disable_arm = g4x_sprite_disable_arm;
1656 plane->get_hw_state = g4x_sprite_get_hw_state;
1657 plane->check_plane = g4x_sprite_check;
1658 plane->max_stride = g4x_sprite_max_stride;
1659 plane->min_alignment = g4x_sprite_min_alignment;
1660 plane->min_cdclk = g4x_sprite_min_cdclk;
1662 if (IS_SANDYBRIDGE(dev_priv)) {
1663 formats = snb_sprite_formats;
1664 num_formats = ARRAY_SIZE(snb_sprite_formats);
1666 plane_funcs = &snb_sprite_funcs;
1668 formats = g4x_sprite_formats;
1669 num_formats = ARRAY_SIZE(g4x_sprite_formats);
1671 plane_funcs = &g4x_sprite_funcs;
1675 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1676 supported_rotations =
1677 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1680 supported_rotations =
1681 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1685 plane->id = PLANE_SPRITE0 + sprite;
1686 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1688 modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1690 ret = drm_universal_plane_init(display->drm, &plane->base,
1692 formats, num_formats, modifiers,
1693 DRM_PLANE_TYPE_OVERLAY,
1694 "sprite %c", sprite_name(display, pipe, sprite));
1700 drm_plane_create_rotation_property(&plane->base,
1702 supported_rotations);
1704 drm_plane_create_color_properties(&plane->base,
1705 BIT(DRM_COLOR_YCBCR_BT601) |
1706 BIT(DRM_COLOR_YCBCR_BT709),
1707 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1708 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1709 DRM_COLOR_YCBCR_BT709,
1710 DRM_COLOR_YCBCR_LIMITED_RANGE);
1713 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1715 intel_plane_helper_add(plane);
1720 intel_plane_free(plane);
1722 return ERR_PTR(ret);