1 // SPDX-License-Identifier: MIT
3 * Copyright © 2020 Intel Corporation
6 #include <drm/drm_atomic_helper.h>
7 #include <drm/drm_damage_helper.h>
8 #include <drm/drm_fourcc.h>
9 #include <drm/drm_plane_helper.h>
12 #include "intel_atomic_plane.h"
13 #include "intel_display_types.h"
16 #include "intel_psr.h"
17 #include "intel_sprite.h"
18 #include "skl_scaler.h"
19 #include "skl_universal_plane.h"
21 static const u32 skl_plane_formats[] = {
28 DRM_FORMAT_XRGB2101010,
29 DRM_FORMAT_XBGR2101010,
30 DRM_FORMAT_XRGB16161616F,
31 DRM_FORMAT_XBGR16161616F,
39 static const u32 skl_planar_formats[] = {
46 DRM_FORMAT_XRGB2101010,
47 DRM_FORMAT_XBGR2101010,
48 DRM_FORMAT_XRGB16161616F,
49 DRM_FORMAT_XBGR16161616F,
58 static const u32 glk_planar_formats[] = {
65 DRM_FORMAT_XRGB2101010,
66 DRM_FORMAT_XBGR2101010,
67 DRM_FORMAT_XRGB16161616F,
68 DRM_FORMAT_XBGR16161616F,
80 static const u32 icl_sdr_y_plane_formats[] = {
87 DRM_FORMAT_XRGB2101010,
88 DRM_FORMAT_XBGR2101010,
89 DRM_FORMAT_ARGB2101010,
90 DRM_FORMAT_ABGR2101010,
99 DRM_FORMAT_XVYU2101010,
100 DRM_FORMAT_XVYU12_16161616,
101 DRM_FORMAT_XVYU16161616,
104 static const u32 icl_sdr_uv_plane_formats[] = {
111 DRM_FORMAT_XRGB2101010,
112 DRM_FORMAT_XBGR2101010,
113 DRM_FORMAT_ARGB2101010,
114 DRM_FORMAT_ABGR2101010,
127 DRM_FORMAT_XVYU2101010,
128 DRM_FORMAT_XVYU12_16161616,
129 DRM_FORMAT_XVYU16161616,
132 static const u32 icl_hdr_plane_formats[] = {
139 DRM_FORMAT_XRGB2101010,
140 DRM_FORMAT_XBGR2101010,
141 DRM_FORMAT_ARGB2101010,
142 DRM_FORMAT_ABGR2101010,
143 DRM_FORMAT_XRGB16161616F,
144 DRM_FORMAT_XBGR16161616F,
145 DRM_FORMAT_ARGB16161616F,
146 DRM_FORMAT_ABGR16161616F,
159 DRM_FORMAT_XVYU2101010,
160 DRM_FORMAT_XVYU12_16161616,
161 DRM_FORMAT_XVYU16161616,
164 static const u64 skl_plane_format_modifiers_noccs[] = {
165 I915_FORMAT_MOD_Yf_TILED,
166 I915_FORMAT_MOD_Y_TILED,
167 I915_FORMAT_MOD_X_TILED,
168 DRM_FORMAT_MOD_LINEAR,
169 DRM_FORMAT_MOD_INVALID
172 static const u64 skl_plane_format_modifiers_ccs[] = {
173 I915_FORMAT_MOD_Yf_TILED_CCS,
174 I915_FORMAT_MOD_Y_TILED_CCS,
175 I915_FORMAT_MOD_Yf_TILED,
176 I915_FORMAT_MOD_Y_TILED,
177 I915_FORMAT_MOD_X_TILED,
178 DRM_FORMAT_MOD_LINEAR,
179 DRM_FORMAT_MOD_INVALID
182 static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
183 I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
184 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
185 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
186 I915_FORMAT_MOD_Y_TILED,
187 I915_FORMAT_MOD_X_TILED,
188 DRM_FORMAT_MOD_LINEAR,
189 DRM_FORMAT_MOD_INVALID
192 static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
193 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
194 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
195 I915_FORMAT_MOD_Y_TILED,
196 I915_FORMAT_MOD_X_TILED,
197 DRM_FORMAT_MOD_LINEAR,
198 DRM_FORMAT_MOD_INVALID
201 int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
204 case PLANE_CTL_FORMAT_RGB_565:
205 return DRM_FORMAT_RGB565;
206 case PLANE_CTL_FORMAT_NV12:
207 return DRM_FORMAT_NV12;
208 case PLANE_CTL_FORMAT_XYUV:
209 return DRM_FORMAT_XYUV8888;
210 case PLANE_CTL_FORMAT_P010:
211 return DRM_FORMAT_P010;
212 case PLANE_CTL_FORMAT_P012:
213 return DRM_FORMAT_P012;
214 case PLANE_CTL_FORMAT_P016:
215 return DRM_FORMAT_P016;
216 case PLANE_CTL_FORMAT_Y210:
217 return DRM_FORMAT_Y210;
218 case PLANE_CTL_FORMAT_Y212:
219 return DRM_FORMAT_Y212;
220 case PLANE_CTL_FORMAT_Y216:
221 return DRM_FORMAT_Y216;
222 case PLANE_CTL_FORMAT_Y410:
223 return DRM_FORMAT_XVYU2101010;
224 case PLANE_CTL_FORMAT_Y412:
225 return DRM_FORMAT_XVYU12_16161616;
226 case PLANE_CTL_FORMAT_Y416:
227 return DRM_FORMAT_XVYU16161616;
229 case PLANE_CTL_FORMAT_XRGB_8888:
232 return DRM_FORMAT_ABGR8888;
234 return DRM_FORMAT_XBGR8888;
237 return DRM_FORMAT_ARGB8888;
239 return DRM_FORMAT_XRGB8888;
241 case PLANE_CTL_FORMAT_XRGB_2101010:
244 return DRM_FORMAT_ABGR2101010;
246 return DRM_FORMAT_XBGR2101010;
249 return DRM_FORMAT_ARGB2101010;
251 return DRM_FORMAT_XRGB2101010;
253 case PLANE_CTL_FORMAT_XRGB_16161616F:
256 return DRM_FORMAT_ABGR16161616F;
258 return DRM_FORMAT_XBGR16161616F;
261 return DRM_FORMAT_ARGB16161616F;
263 return DRM_FORMAT_XRGB16161616F;
268 static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
270 if (HAS_D12_PLANE_MINIMIZATION(i915))
271 return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
273 return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
276 bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
277 enum plane_id plane_id)
279 return DISPLAY_VER(dev_priv) >= 11 &&
280 icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
283 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
285 return DISPLAY_VER(dev_priv) >= 11 &&
286 icl_hdr_plane_mask() & BIT(plane_id);
290 skl_plane_ratio(const struct intel_crtc_state *crtc_state,
291 const struct intel_plane_state *plane_state,
292 unsigned int *num, unsigned int *den)
294 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
295 const struct drm_framebuffer *fb = plane_state->hw.fb;
297 if (fb->format->cpp[0] == 8) {
298 if (DISPLAY_VER(dev_priv) >= 10) {
311 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
312 const struct intel_plane_state *plane_state)
314 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
315 unsigned int num, den;
316 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
318 skl_plane_ratio(crtc_state, plane_state, &num, &den);
320 /* two pixels per clock on glk+ */
321 if (DISPLAY_VER(dev_priv) >= 10)
324 return DIV_ROUND_UP(pixel_rate * num, den);
327 static int skl_plane_max_width(const struct drm_framebuffer *fb,
329 unsigned int rotation)
331 int cpp = fb->format->cpp[color_plane];
333 switch (fb->modifier) {
334 case DRM_FORMAT_MOD_LINEAR:
335 case I915_FORMAT_MOD_X_TILED:
337 * Validated limit is 4k, but has 5k should
338 * work apart from the following features:
339 * - Ytile (already limited to 4k)
340 * - FP16 (already limited to 4k)
341 * - render compression (already limited to 4k)
342 * - KVMR sprite and cursor (don't care)
343 * - horizontal panning (TODO verify this)
344 * - pipe and plane scaling (TODO verify this)
350 case I915_FORMAT_MOD_Y_TILED_CCS:
351 case I915_FORMAT_MOD_Yf_TILED_CCS:
352 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
353 /* FIXME AUX plane? */
354 case I915_FORMAT_MOD_Y_TILED:
355 case I915_FORMAT_MOD_Yf_TILED:
361 MISSING_CASE(fb->modifier);
366 static int glk_plane_max_width(const struct drm_framebuffer *fb,
368 unsigned int rotation)
370 int cpp = fb->format->cpp[color_plane];
372 switch (fb->modifier) {
373 case DRM_FORMAT_MOD_LINEAR:
374 case I915_FORMAT_MOD_X_TILED:
379 case I915_FORMAT_MOD_Y_TILED_CCS:
380 case I915_FORMAT_MOD_Yf_TILED_CCS:
381 /* FIXME AUX plane? */
382 case I915_FORMAT_MOD_Y_TILED:
383 case I915_FORMAT_MOD_Yf_TILED:
389 MISSING_CASE(fb->modifier);
394 static int icl_plane_min_width(const struct drm_framebuffer *fb,
396 unsigned int rotation)
398 /* Wa_14011264657, Wa_14011050563: gen11+ */
399 switch (fb->format->format) {
402 case DRM_FORMAT_RGB565:
404 case DRM_FORMAT_XRGB8888:
405 case DRM_FORMAT_XBGR8888:
406 case DRM_FORMAT_ARGB8888:
407 case DRM_FORMAT_ABGR8888:
408 case DRM_FORMAT_XRGB2101010:
409 case DRM_FORMAT_XBGR2101010:
410 case DRM_FORMAT_ARGB2101010:
411 case DRM_FORMAT_ABGR2101010:
412 case DRM_FORMAT_XVYU2101010:
413 case DRM_FORMAT_Y212:
414 case DRM_FORMAT_Y216:
416 case DRM_FORMAT_NV12:
418 case DRM_FORMAT_P010:
419 case DRM_FORMAT_P012:
420 case DRM_FORMAT_P016:
422 case DRM_FORMAT_XRGB16161616F:
423 case DRM_FORMAT_XBGR16161616F:
424 case DRM_FORMAT_ARGB16161616F:
425 case DRM_FORMAT_ABGR16161616F:
426 case DRM_FORMAT_XVYU12_16161616:
427 case DRM_FORMAT_XVYU16161616:
434 static int icl_plane_max_width(const struct drm_framebuffer *fb,
436 unsigned int rotation)
441 static int skl_plane_max_height(const struct drm_framebuffer *fb,
443 unsigned int rotation)
448 static int icl_plane_max_height(const struct drm_framebuffer *fb,
450 unsigned int rotation)
456 skl_plane_max_stride(struct intel_plane *plane,
457 u32 pixel_format, u64 modifier,
458 unsigned int rotation)
460 const struct drm_format_info *info = drm_format_info(pixel_format);
461 int cpp = info->cpp[0];
464 * "The stride in bytes must not exceed the
465 * of the size of 8K pixels and 32K bytes."
467 if (drm_rotation_90_or_270(rotation))
468 return min(8192, 32768 / cpp);
470 return min(8192 * cpp, 32768);
474 /* Preoffset values for YUV to RGB Conversion */
475 #define PREOFF_YUV_TO_RGB_HI 0x1800
476 #define PREOFF_YUV_TO_RGB_ME 0x0000
477 #define PREOFF_YUV_TO_RGB_LO 0x1800
479 #define ROFF(x) (((x) & 0xffff) << 16)
480 #define GOFF(x) (((x) & 0xffff) << 0)
481 #define BOFF(x) (((x) & 0xffff) << 16)
484 * Programs the input color space conversion stage for ICL HDR planes.
485 * Note that it is assumed that this stage always happens after YUV
486 * range correction. Thus, the input to this stage is assumed to be
487 * in full-range YCbCr.
490 icl_program_input_csc(struct intel_plane *plane,
491 const struct intel_crtc_state *crtc_state,
492 const struct intel_plane_state *plane_state)
494 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
495 enum pipe pipe = plane->pipe;
496 enum plane_id plane_id = plane->id;
498 static const u16 input_csc_matrix[][9] = {
500 * BT.601 full range YCbCr -> full range RGB
501 * The matrix required is :
502 * [1.000, 0.000, 1.371,
503 * 1.000, -0.336, -0.698,
504 * 1.000, 1.732, 0.0000]
506 [DRM_COLOR_YCBCR_BT601] = {
508 0x8B28, 0x7800, 0x9AC0,
512 * BT.709 full range YCbCr -> full range RGB
513 * The matrix required is :
514 * [1.000, 0.000, 1.574,
515 * 1.000, -0.187, -0.468,
516 * 1.000, 1.855, 0.0000]
518 [DRM_COLOR_YCBCR_BT709] = {
520 0x9EF8, 0x7800, 0xAC00,
524 * BT.2020 full range YCbCr -> full range RGB
525 * The matrix required is :
526 * [1.000, 0.000, 1.474,
527 * 1.000, -0.1645, -0.5713,
528 * 1.000, 1.8814, 0.0000]
530 [DRM_COLOR_YCBCR_BT2020] = {
532 0x8928, 0x7800, 0xAA88,
536 const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
538 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
539 ROFF(csc[0]) | GOFF(csc[1]));
540 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
542 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
543 ROFF(csc[3]) | GOFF(csc[4]));
544 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
546 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
547 ROFF(csc[6]) | GOFF(csc[7]));
548 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
551 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
552 PREOFF_YUV_TO_RGB_HI);
553 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
554 PREOFF_YUV_TO_RGB_ME);
555 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
556 PREOFF_YUV_TO_RGB_LO);
557 intel_de_write_fw(dev_priv,
558 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
559 intel_de_write_fw(dev_priv,
560 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
561 intel_de_write_fw(dev_priv,
562 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
565 static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
566 int color_plane, unsigned int rotation)
569 * The stride is either expressed as a multiple of 64 bytes chunks for
570 * linear buffers or in number of tiles for tiled buffers.
572 if (is_surface_linear(fb, color_plane))
574 else if (drm_rotation_90_or_270(rotation))
575 return intel_tile_height(fb, color_plane);
577 return intel_tile_width_bytes(fb, color_plane);
580 static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
583 const struct drm_framebuffer *fb = plane_state->hw.fb;
584 unsigned int rotation = plane_state->hw.rotation;
585 u32 stride = plane_state->view.color_plane[color_plane].stride;
587 if (color_plane >= fb->format->num_planes)
590 return stride / skl_plane_stride_mult(fb, color_plane, rotation);
594 skl_disable_plane(struct intel_plane *plane,
595 const struct intel_crtc_state *crtc_state)
597 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
598 enum plane_id plane_id = plane->id;
599 enum pipe pipe = plane->pipe;
600 unsigned long irqflags;
602 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
604 if (icl_is_hdr_plane(dev_priv, plane_id))
605 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
607 skl_write_plane_wm(plane, crtc_state);
609 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
610 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
612 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
616 skl_plane_get_hw_state(struct intel_plane *plane,
619 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
620 enum intel_display_power_domain power_domain;
621 enum plane_id plane_id = plane->id;
622 intel_wakeref_t wakeref;
625 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
626 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
630 ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
634 intel_display_power_put(dev_priv, power_domain, wakeref);
639 static u32 skl_plane_ctl_format(u32 pixel_format)
641 switch (pixel_format) {
643 return PLANE_CTL_FORMAT_INDEXED;
644 case DRM_FORMAT_RGB565:
645 return PLANE_CTL_FORMAT_RGB_565;
646 case DRM_FORMAT_XBGR8888:
647 case DRM_FORMAT_ABGR8888:
648 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
649 case DRM_FORMAT_XRGB8888:
650 case DRM_FORMAT_ARGB8888:
651 return PLANE_CTL_FORMAT_XRGB_8888;
652 case DRM_FORMAT_XBGR2101010:
653 case DRM_FORMAT_ABGR2101010:
654 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
655 case DRM_FORMAT_XRGB2101010:
656 case DRM_FORMAT_ARGB2101010:
657 return PLANE_CTL_FORMAT_XRGB_2101010;
658 case DRM_FORMAT_XBGR16161616F:
659 case DRM_FORMAT_ABGR16161616F:
660 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
661 case DRM_FORMAT_XRGB16161616F:
662 case DRM_FORMAT_ARGB16161616F:
663 return PLANE_CTL_FORMAT_XRGB_16161616F;
664 case DRM_FORMAT_XYUV8888:
665 return PLANE_CTL_FORMAT_XYUV;
666 case DRM_FORMAT_YUYV:
667 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
668 case DRM_FORMAT_YVYU:
669 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
670 case DRM_FORMAT_UYVY:
671 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
672 case DRM_FORMAT_VYUY:
673 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
674 case DRM_FORMAT_NV12:
675 return PLANE_CTL_FORMAT_NV12;
676 case DRM_FORMAT_P010:
677 return PLANE_CTL_FORMAT_P010;
678 case DRM_FORMAT_P012:
679 return PLANE_CTL_FORMAT_P012;
680 case DRM_FORMAT_P016:
681 return PLANE_CTL_FORMAT_P016;
682 case DRM_FORMAT_Y210:
683 return PLANE_CTL_FORMAT_Y210;
684 case DRM_FORMAT_Y212:
685 return PLANE_CTL_FORMAT_Y212;
686 case DRM_FORMAT_Y216:
687 return PLANE_CTL_FORMAT_Y216;
688 case DRM_FORMAT_XVYU2101010:
689 return PLANE_CTL_FORMAT_Y410;
690 case DRM_FORMAT_XVYU12_16161616:
691 return PLANE_CTL_FORMAT_Y412;
692 case DRM_FORMAT_XVYU16161616:
693 return PLANE_CTL_FORMAT_Y416;
695 MISSING_CASE(pixel_format);
701 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
703 if (!plane_state->hw.fb->format->has_alpha)
704 return PLANE_CTL_ALPHA_DISABLE;
706 switch (plane_state->hw.pixel_blend_mode) {
707 case DRM_MODE_BLEND_PIXEL_NONE:
708 return PLANE_CTL_ALPHA_DISABLE;
709 case DRM_MODE_BLEND_PREMULTI:
710 return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
711 case DRM_MODE_BLEND_COVERAGE:
712 return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
714 MISSING_CASE(plane_state->hw.pixel_blend_mode);
715 return PLANE_CTL_ALPHA_DISABLE;
719 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
721 if (!plane_state->hw.fb->format->has_alpha)
722 return PLANE_COLOR_ALPHA_DISABLE;
724 switch (plane_state->hw.pixel_blend_mode) {
725 case DRM_MODE_BLEND_PIXEL_NONE:
726 return PLANE_COLOR_ALPHA_DISABLE;
727 case DRM_MODE_BLEND_PREMULTI:
728 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
729 case DRM_MODE_BLEND_COVERAGE:
730 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
732 MISSING_CASE(plane_state->hw.pixel_blend_mode);
733 return PLANE_COLOR_ALPHA_DISABLE;
737 static u32 skl_plane_ctl_tiling(u64 fb_modifier)
739 switch (fb_modifier) {
740 case DRM_FORMAT_MOD_LINEAR:
742 case I915_FORMAT_MOD_X_TILED:
743 return PLANE_CTL_TILED_X;
744 case I915_FORMAT_MOD_Y_TILED:
745 return PLANE_CTL_TILED_Y;
746 case I915_FORMAT_MOD_Y_TILED_CCS:
747 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
748 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
749 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
750 return PLANE_CTL_TILED_Y |
751 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
752 PLANE_CTL_CLEAR_COLOR_DISABLE;
753 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
754 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
755 case I915_FORMAT_MOD_Yf_TILED:
756 return PLANE_CTL_TILED_YF;
757 case I915_FORMAT_MOD_Yf_TILED_CCS:
758 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
760 MISSING_CASE(fb_modifier);
766 static u32 skl_plane_ctl_rotate(unsigned int rotate)
769 case DRM_MODE_ROTATE_0:
772 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
773 * while i915 HW rotation is clockwise, thats why this swapping.
775 case DRM_MODE_ROTATE_90:
776 return PLANE_CTL_ROTATE_270;
777 case DRM_MODE_ROTATE_180:
778 return PLANE_CTL_ROTATE_180;
779 case DRM_MODE_ROTATE_270:
780 return PLANE_CTL_ROTATE_90;
782 MISSING_CASE(rotate);
788 static u32 cnl_plane_ctl_flip(unsigned int reflect)
793 case DRM_MODE_REFLECT_X:
794 return PLANE_CTL_FLIP_HORIZONTAL;
795 case DRM_MODE_REFLECT_Y:
797 MISSING_CASE(reflect);
803 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
805 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
808 if (DISPLAY_VER(dev_priv) >= 10)
811 if (crtc_state->gamma_enable)
812 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
814 if (crtc_state->csc_enable)
815 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
820 static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
821 const struct intel_plane_state *plane_state)
823 struct drm_i915_private *dev_priv =
824 to_i915(plane_state->uapi.plane->dev);
825 const struct drm_framebuffer *fb = plane_state->hw.fb;
826 unsigned int rotation = plane_state->hw.rotation;
827 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
830 plane_ctl = PLANE_CTL_ENABLE;
832 if (DISPLAY_VER(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
833 plane_ctl |= skl_plane_ctl_alpha(plane_state);
834 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
836 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
837 plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
839 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
840 plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
843 plane_ctl |= skl_plane_ctl_format(fb->format->format);
844 plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
845 plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
847 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
848 plane_ctl |= cnl_plane_ctl_flip(rotation &
849 DRM_MODE_REFLECT_MASK);
851 if (key->flags & I915_SET_COLORKEY_DESTINATION)
852 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
853 else if (key->flags & I915_SET_COLORKEY_SOURCE)
854 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
859 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
861 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
862 u32 plane_color_ctl = 0;
864 if (DISPLAY_VER(dev_priv) >= 11)
865 return plane_color_ctl;
867 if (crtc_state->gamma_enable)
868 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
870 if (crtc_state->csc_enable)
871 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
873 return plane_color_ctl;
876 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
877 const struct intel_plane_state *plane_state)
879 struct drm_i915_private *dev_priv =
880 to_i915(plane_state->uapi.plane->dev);
881 const struct drm_framebuffer *fb = plane_state->hw.fb;
882 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
883 u32 plane_color_ctl = 0;
885 plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
886 plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
888 if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
889 switch (plane_state->hw.color_encoding) {
890 case DRM_COLOR_YCBCR_BT709:
891 plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
893 case DRM_COLOR_YCBCR_BT2020:
895 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
899 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
901 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
902 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
903 } else if (fb->format->is_yuv) {
904 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
905 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
906 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
909 return plane_color_ctl;
913 skl_program_plane(struct intel_plane *plane,
914 const struct intel_crtc_state *crtc_state,
915 const struct intel_plane_state *plane_state,
918 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
919 enum plane_id plane_id = plane->id;
920 enum pipe pipe = plane->pipe;
921 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
922 u32 surf_addr = plane_state->view.color_plane[color_plane].offset;
923 u32 stride = skl_plane_stride(plane_state, color_plane);
924 const struct drm_framebuffer *fb = plane_state->hw.fb;
925 int aux_plane = skl_main_to_aux_plane(fb, color_plane);
926 int crtc_x = plane_state->uapi.dst.x1;
927 int crtc_y = plane_state->uapi.dst.y1;
928 u32 x = plane_state->view.color_plane[color_plane].x;
929 u32 y = plane_state->view.color_plane[color_plane].y;
930 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
931 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
932 u8 alpha = plane_state->hw.alpha >> 8;
933 u32 plane_color_ctl = 0, aux_dist = 0;
934 unsigned long irqflags;
936 u32 plane_ctl = plane_state->ctl;
938 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
940 if (DISPLAY_VER(dev_priv) >= 10)
941 plane_color_ctl = plane_state->color_ctl |
942 glk_plane_color_ctl_crtc(crtc_state);
944 /* Sizes are 0 based */
948 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
950 keymsk = key->channel_mask & 0x7ffffff;
952 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
954 /* The scaler will handle the output position */
955 if (plane_state->scaler_id >= 0) {
961 aux_dist = plane_state->view.color_plane[aux_plane].offset - surf_addr;
963 if (DISPLAY_VER(dev_priv) < 12)
964 aux_dist |= skl_plane_stride(plane_state, aux_plane);
967 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
969 intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
970 intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
971 (crtc_y << 16) | crtc_x);
972 intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
973 (src_h << 16) | src_w);
975 intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
977 if (icl_is_hdr_plane(dev_priv, plane_id))
978 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
979 plane_state->cus_ctl);
981 if (DISPLAY_VER(dev_priv) >= 10)
982 intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
985 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
986 icl_program_input_csc(plane, crtc_state, plane_state);
988 if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)
989 intel_uncore_write64_fw(&dev_priv->uncore,
990 PLANE_CC_VAL(pipe, plane_id), plane_state->ccval);
992 skl_write_plane_wm(plane, crtc_state);
994 intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
996 intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
997 intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
999 intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1002 if (DISPLAY_VER(dev_priv) < 11)
1003 intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
1004 (plane_state->view.color_plane[1].y << 16) |
1005 plane_state->view.color_plane[1].x);
1007 if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
1008 intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
1011 * The control register self-arms if the plane was previously
1012 * disabled. Try to make the plane enable atomic by writing
1013 * the control register just before the surface register.
1015 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1016 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1017 intel_plane_ggtt_offset(plane_state) + surf_addr);
1019 if (plane_state->scaler_id >= 0)
1020 skl_program_plane_scaler(plane, crtc_state, plane_state);
1022 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1026 skl_plane_async_flip(struct intel_plane *plane,
1027 const struct intel_crtc_state *crtc_state,
1028 const struct intel_plane_state *plane_state,
1031 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1032 unsigned long irqflags;
1033 enum plane_id plane_id = plane->id;
1034 enum pipe pipe = plane->pipe;
1035 u32 surf_addr = plane_state->view.color_plane[0].offset;
1036 u32 plane_ctl = plane_state->ctl;
1038 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1041 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1043 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1045 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1046 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1047 intel_plane_ggtt_offset(plane_state) + surf_addr);
1049 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1053 skl_update_plane(struct intel_plane *plane,
1054 const struct intel_crtc_state *crtc_state,
1055 const struct intel_plane_state *plane_state)
1057 int color_plane = 0;
1059 if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1060 /* Program the UV plane on planar master */
1063 skl_program_plane(plane, crtc_state, plane_state, color_plane);
1066 static bool intel_format_is_p01x(u32 format)
1069 case DRM_FORMAT_P010:
1070 case DRM_FORMAT_P012:
1071 case DRM_FORMAT_P016:
1078 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1079 const struct intel_plane_state *plane_state)
1081 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1082 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1083 const struct drm_framebuffer *fb = plane_state->hw.fb;
1084 unsigned int rotation = plane_state->hw.rotation;
1085 struct drm_format_name_buf format_name;
1090 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1091 is_ccs_modifier(fb->modifier)) {
1092 drm_dbg_kms(&dev_priv->drm,
1093 "RC support only with 0/180 degree rotation (%x)\n",
1098 if (rotation & DRM_MODE_REFLECT_X &&
1099 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1100 drm_dbg_kms(&dev_priv->drm,
1101 "horizontal flip is not supported with linear surface formats\n");
1105 if (drm_rotation_90_or_270(rotation)) {
1106 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1107 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1108 drm_dbg_kms(&dev_priv->drm,
1109 "Y/Yf tiling required for 90/270!\n");
1114 * 90/270 is not allowed with RGB64 16:16:16:16 and
1115 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1117 switch (fb->format->format) {
1118 case DRM_FORMAT_RGB565:
1119 if (DISPLAY_VER(dev_priv) >= 11)
1123 case DRM_FORMAT_XRGB16161616F:
1124 case DRM_FORMAT_XBGR16161616F:
1125 case DRM_FORMAT_ARGB16161616F:
1126 case DRM_FORMAT_ABGR16161616F:
1127 case DRM_FORMAT_Y210:
1128 case DRM_FORMAT_Y212:
1129 case DRM_FORMAT_Y216:
1130 case DRM_FORMAT_XVYU12_16161616:
1131 case DRM_FORMAT_XVYU16161616:
1132 drm_dbg_kms(&dev_priv->drm,
1133 "Unsupported pixel format %s for 90/270!\n",
1134 drm_get_format_name(fb->format->format,
1142 /* Y-tiling is not supported in IF-ID Interlace mode */
1143 if (crtc_state->hw.enable &&
1144 crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1145 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1146 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1147 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1148 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
1149 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
1150 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
1151 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) {
1152 drm_dbg_kms(&dev_priv->drm,
1153 "Y/Yf tiling not supported in IF-ID mode\n");
1157 /* Wa_1606054188:tgl,adl-s */
1158 if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1159 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1160 intel_format_is_p01x(fb->format->format)) {
1161 drm_dbg_kms(&dev_priv->drm,
1162 "Source color keying not supported with P01x formats\n");
1169 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1170 const struct intel_plane_state *plane_state)
1172 struct drm_i915_private *dev_priv =
1173 to_i915(plane_state->uapi.plane->dev);
1174 int crtc_x = plane_state->uapi.dst.x1;
1175 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1176 int pipe_src_w = crtc_state->pipe_src_w;
1179 * Display WA #1175: cnl,glk
1180 * Planes other than the cursor may cause FIFO underflow and display
1181 * corruption if starting less than 4 pixels from the right edge of
1183 * Besides the above WA fix the similar problem, where planes other
1184 * than the cursor ending less than 4 pixels from the left edge of the
1185 * screen may cause FIFO underflow and display corruption.
1187 if (IS_DISPLAY_VER(dev_priv, 10) &&
1188 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1189 drm_dbg_kms(&dev_priv->drm,
1190 "requested plane X %s position %d invalid (valid range %d-%d)\n",
1191 crtc_x + crtc_w < 4 ? "end" : "start",
1192 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1200 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1202 const struct drm_framebuffer *fb = plane_state->hw.fb;
1203 unsigned int rotation = plane_state->hw.rotation;
1204 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1206 /* Display WA #1106 */
1207 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1209 (rotation == DRM_MODE_ROTATE_270 ||
1210 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1211 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1218 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1219 const struct drm_framebuffer *fb)
1222 * We don't yet know the final source width nor
1223 * whether we can use the HQ scaler mode. Assume
1225 * FIXME need to properly check this later.
1227 if (DISPLAY_VER(dev_priv) >= 10 ||
1228 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1234 static int intel_plane_min_width(struct intel_plane *plane,
1235 const struct drm_framebuffer *fb,
1237 unsigned int rotation)
1239 if (plane->min_width)
1240 return plane->min_width(fb, color_plane, rotation);
1245 static int intel_plane_max_width(struct intel_plane *plane,
1246 const struct drm_framebuffer *fb,
1248 unsigned int rotation)
1250 if (plane->max_width)
1251 return plane->max_width(fb, color_plane, rotation);
1256 static int intel_plane_max_height(struct intel_plane *plane,
1257 const struct drm_framebuffer *fb,
1259 unsigned int rotation)
1261 if (plane->max_height)
1262 return plane->max_height(fb, color_plane, rotation);
1268 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1269 int main_x, int main_y, u32 main_offset,
1272 const struct drm_framebuffer *fb = plane_state->hw.fb;
1273 int aux_x = plane_state->view.color_plane[ccs_plane].x;
1274 int aux_y = plane_state->view.color_plane[ccs_plane].y;
1275 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1276 u32 alignment = intel_surf_alignment(fb, ccs_plane);
1280 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1281 while (aux_offset >= main_offset && aux_y <= main_y) {
1284 if (aux_x == main_x && aux_y == main_y)
1287 if (aux_offset == 0)
1292 aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1298 aux_x = x * hsub + aux_x % hsub;
1299 aux_y = y * vsub + aux_y % vsub;
1302 if (aux_x != main_x || aux_y != main_y)
1305 plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1306 plane_state->view.color_plane[ccs_plane].x = aux_x;
1307 plane_state->view.color_plane[ccs_plane].y = aux_y;
1313 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1314 int *x, int *y, u32 *offset)
1316 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1317 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1318 const struct drm_framebuffer *fb = plane_state->hw.fb;
1319 const int aux_plane = skl_main_to_aux_plane(fb, 0);
1320 const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1321 const u32 alignment = intel_surf_alignment(fb, 0);
1322 const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1324 intel_add_fb_offsets(x, y, plane_state, 0);
1325 *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1326 if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1330 * AUX surface offset is specified as the distance from the
1331 * main surface offset, and it must be non-negative. Make
1332 * sure that is what we will get.
1334 if (aux_plane && *offset > aux_offset)
1335 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1337 aux_offset & ~(alignment - 1));
1340 * When using an X-tiled surface, the plane blows up
1341 * if the x offset + width exceed the stride.
1343 * TODO: linear and Y-tiled seem fine, Yf untested,
1345 if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1346 int cpp = fb->format->cpp[0];
1348 while ((*x + w) * cpp > plane_state->view.color_plane[0].stride) {
1350 drm_dbg_kms(&dev_priv->drm,
1351 "Unable to find suitable display surface offset due to X-tiling\n");
1355 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1357 *offset - alignment);
1364 static int skl_check_main_surface(struct intel_plane_state *plane_state)
1366 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1367 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1368 const struct drm_framebuffer *fb = plane_state->hw.fb;
1369 const unsigned int rotation = plane_state->hw.rotation;
1370 int x = plane_state->uapi.src.x1 >> 16;
1371 int y = plane_state->uapi.src.y1 >> 16;
1372 const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1373 const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1374 const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1375 const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1376 const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1377 const int aux_plane = skl_main_to_aux_plane(fb, 0);
1378 const u32 alignment = intel_surf_alignment(fb, 0);
1382 if (w > max_width || w < min_width || h > max_height) {
1383 drm_dbg_kms(&dev_priv->drm,
1384 "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1385 w, h, min_width, max_width, max_height);
1389 ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1394 * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1395 * they match with the main surface x/y offsets.
1397 if (is_ccs_modifier(fb->modifier)) {
1398 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1399 offset, aux_plane)) {
1403 offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1404 offset, offset - alignment);
1407 if (x != plane_state->view.color_plane[aux_plane].x ||
1408 y != plane_state->view.color_plane[aux_plane].y) {
1409 drm_dbg_kms(&dev_priv->drm,
1410 "Unable to find suitable display surface offset due to CCS\n");
1415 drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1417 plane_state->view.color_plane[0].offset = offset;
1418 plane_state->view.color_plane[0].x = x;
1419 plane_state->view.color_plane[0].y = y;
1422 * Put the final coordinates back so that the src
1423 * coordinate checks will see the right values.
1425 drm_rect_translate_to(&plane_state->uapi.src,
1431 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1433 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1434 struct drm_i915_private *i915 = to_i915(plane->base.dev);
1435 const struct drm_framebuffer *fb = plane_state->hw.fb;
1436 unsigned int rotation = plane_state->hw.rotation;
1438 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
1439 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
1440 int x = plane_state->uapi.src.x1 >> 17;
1441 int y = plane_state->uapi.src.y1 >> 17;
1442 int w = drm_rect_width(&plane_state->uapi.src) >> 17;
1443 int h = drm_rect_height(&plane_state->uapi.src) >> 17;
1446 /* FIXME not quite sure how/if these apply to the chroma plane */
1447 if (w > max_width || h > max_height) {
1448 drm_dbg_kms(&i915->drm,
1449 "CbCr source size %dx%d too big (limit %dx%d)\n",
1450 w, h, max_width, max_height);
1454 intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
1455 offset = intel_plane_compute_aligned_offset(&x, &y,
1456 plane_state, uv_plane);
1458 if (is_ccs_modifier(fb->modifier)) {
1459 int ccs_plane = main_to_ccs_plane(fb, uv_plane);
1460 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1461 u32 alignment = intel_surf_alignment(fb, uv_plane);
1463 if (offset > aux_offset)
1464 offset = intel_plane_adjust_aligned_offset(&x, &y,
1468 aux_offset & ~(alignment - 1));
1470 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1471 offset, ccs_plane)) {
1475 offset = intel_plane_adjust_aligned_offset(&x, &y,
1478 offset, offset - alignment);
1481 if (x != plane_state->view.color_plane[ccs_plane].x ||
1482 y != plane_state->view.color_plane[ccs_plane].y) {
1483 drm_dbg_kms(&i915->drm,
1484 "Unable to find suitable display surface offset due to CCS\n");
1489 drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
1491 plane_state->view.color_plane[uv_plane].offset = offset;
1492 plane_state->view.color_plane[uv_plane].x = x;
1493 plane_state->view.color_plane[uv_plane].y = y;
1498 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
1500 const struct drm_framebuffer *fb = plane_state->hw.fb;
1501 int src_x = plane_state->uapi.src.x1 >> 16;
1502 int src_y = plane_state->uapi.src.y1 >> 16;
1506 for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
1507 int main_hsub, main_vsub;
1511 if (!is_ccs_plane(fb, ccs_plane) ||
1512 is_gen12_ccs_cc_plane(fb, ccs_plane))
1515 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
1516 skl_ccs_to_main_plane(fb, ccs_plane));
1517 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1524 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
1526 offset = intel_plane_compute_aligned_offset(&x, &y,
1530 plane_state->view.color_plane[ccs_plane].offset = offset;
1531 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
1532 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
1538 static int skl_check_plane_surface(struct intel_plane_state *plane_state)
1540 const struct drm_framebuffer *fb = plane_state->hw.fb;
1543 ret = intel_plane_compute_gtt(plane_state);
1547 if (!plane_state->uapi.visible)
1551 * Handle the AUX surface first since the main surface setup depends on
1554 if (is_ccs_modifier(fb->modifier)) {
1555 ret = skl_check_ccs_aux_surface(plane_state);
1560 if (intel_format_info_is_yuv_semiplanar(fb->format,
1562 ret = skl_check_nv12_aux_surface(plane_state);
1567 ret = skl_check_main_surface(plane_state);
1574 static bool skl_fb_scalable(const struct drm_framebuffer *fb)
1579 switch (fb->format->format) {
1582 case DRM_FORMAT_XRGB16161616F:
1583 case DRM_FORMAT_ARGB16161616F:
1584 case DRM_FORMAT_XBGR16161616F:
1585 case DRM_FORMAT_ABGR16161616F:
1586 return DISPLAY_VER(to_i915(fb->dev)) >= 11;
1592 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1593 struct intel_plane_state *plane_state)
1595 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1596 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1597 const struct drm_framebuffer *fb = plane_state->hw.fb;
1598 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1599 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1602 ret = skl_plane_check_fb(crtc_state, plane_state);
1606 /* use scaler when colorkey is not required */
1607 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
1609 max_scale = skl_plane_max_scale(dev_priv, fb);
1612 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1613 min_scale, max_scale, true);
1617 ret = skl_check_plane_surface(plane_state);
1621 if (!plane_state->uapi.visible)
1624 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1628 ret = intel_plane_check_src_coordinates(plane_state);
1632 ret = skl_plane_check_nv12_rotation(plane_state);
1636 /* HW only has 8 bits pixel precision, disable plane if invisible */
1637 if (!(plane_state->hw.alpha >> 8))
1638 plane_state->uapi.visible = false;
1640 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1642 if (DISPLAY_VER(dev_priv) >= 10)
1643 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1646 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1647 icl_is_hdr_plane(dev_priv, plane->id))
1648 /* Enable and use MPEG-2 chroma siting */
1649 plane_state->cus_ctl = PLANE_CUS_ENABLE |
1650 PLANE_CUS_HPHASE_0 |
1651 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
1653 plane_state->cus_ctl = 0;
1658 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
1659 enum pipe pipe, enum plane_id plane_id)
1661 if (!HAS_FBC(dev_priv))
1664 return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
1667 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
1668 enum pipe pipe, enum plane_id plane_id)
1670 /* Display WA #0870: skl, bxt */
1671 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
1674 if (IS_DISPLAY_VER(dev_priv, 9) && pipe == PIPE_C)
1677 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
1683 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
1684 enum pipe pipe, enum plane_id plane_id,
1687 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1688 *num_formats = ARRAY_SIZE(skl_planar_formats);
1689 return skl_planar_formats;
1691 *num_formats = ARRAY_SIZE(skl_plane_formats);
1692 return skl_plane_formats;
1696 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
1697 enum pipe pipe, enum plane_id plane_id,
1700 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1701 *num_formats = ARRAY_SIZE(glk_planar_formats);
1702 return glk_planar_formats;
1704 *num_formats = ARRAY_SIZE(skl_plane_formats);
1705 return skl_plane_formats;
1709 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
1710 enum pipe pipe, enum plane_id plane_id,
1713 if (icl_is_hdr_plane(dev_priv, plane_id)) {
1714 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
1715 return icl_hdr_plane_formats;
1716 } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
1717 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
1718 return icl_sdr_y_plane_formats;
1720 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
1721 return icl_sdr_uv_plane_formats;
1725 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1726 enum pipe pipe, enum plane_id plane_id)
1728 if (plane_id == PLANE_CURSOR)
1731 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
1734 if (IS_GEMINILAKE(dev_priv))
1735 return pipe != PIPE_C;
1737 return pipe != PIPE_C &&
1738 (plane_id == PLANE_PRIMARY ||
1739 plane_id == PLANE_SPRITE0);
1742 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1743 u32 format, u64 modifier)
1745 struct intel_plane *plane = to_intel_plane(_plane);
1748 case DRM_FORMAT_MOD_LINEAR:
1749 case I915_FORMAT_MOD_X_TILED:
1750 case I915_FORMAT_MOD_Y_TILED:
1751 case I915_FORMAT_MOD_Yf_TILED:
1753 case I915_FORMAT_MOD_Y_TILED_CCS:
1754 case I915_FORMAT_MOD_Yf_TILED_CCS:
1755 if (!plane->has_ccs)
1763 case DRM_FORMAT_XRGB8888:
1764 case DRM_FORMAT_XBGR8888:
1765 case DRM_FORMAT_ARGB8888:
1766 case DRM_FORMAT_ABGR8888:
1767 if (is_ccs_modifier(modifier))
1770 case DRM_FORMAT_RGB565:
1771 case DRM_FORMAT_XRGB2101010:
1772 case DRM_FORMAT_XBGR2101010:
1773 case DRM_FORMAT_ARGB2101010:
1774 case DRM_FORMAT_ABGR2101010:
1775 case DRM_FORMAT_YUYV:
1776 case DRM_FORMAT_YVYU:
1777 case DRM_FORMAT_UYVY:
1778 case DRM_FORMAT_VYUY:
1779 case DRM_FORMAT_NV12:
1780 case DRM_FORMAT_XYUV8888:
1781 case DRM_FORMAT_P010:
1782 case DRM_FORMAT_P012:
1783 case DRM_FORMAT_P016:
1784 case DRM_FORMAT_XVYU2101010:
1785 if (modifier == I915_FORMAT_MOD_Yf_TILED)
1789 case DRM_FORMAT_XBGR16161616F:
1790 case DRM_FORMAT_ABGR16161616F:
1791 case DRM_FORMAT_XRGB16161616F:
1792 case DRM_FORMAT_ARGB16161616F:
1793 case DRM_FORMAT_Y210:
1794 case DRM_FORMAT_Y212:
1795 case DRM_FORMAT_Y216:
1796 case DRM_FORMAT_XVYU12_16161616:
1797 case DRM_FORMAT_XVYU16161616:
1798 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1799 modifier == I915_FORMAT_MOD_X_TILED ||
1800 modifier == I915_FORMAT_MOD_Y_TILED)
1808 static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
1809 enum plane_id plane_id)
1811 /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
1812 if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
1813 IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0))
1816 return plane_id < PLANE_SPRITE4;
1819 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
1820 u32 format, u64 modifier)
1822 struct drm_i915_private *dev_priv = to_i915(_plane->dev);
1823 struct intel_plane *plane = to_intel_plane(_plane);
1826 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
1827 if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
1830 case DRM_FORMAT_MOD_LINEAR:
1831 case I915_FORMAT_MOD_X_TILED:
1832 case I915_FORMAT_MOD_Y_TILED:
1833 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
1834 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
1841 case DRM_FORMAT_XRGB8888:
1842 case DRM_FORMAT_XBGR8888:
1843 case DRM_FORMAT_ARGB8888:
1844 case DRM_FORMAT_ABGR8888:
1845 if (is_ccs_modifier(modifier))
1848 case DRM_FORMAT_YUYV:
1849 case DRM_FORMAT_YVYU:
1850 case DRM_FORMAT_UYVY:
1851 case DRM_FORMAT_VYUY:
1852 case DRM_FORMAT_NV12:
1853 case DRM_FORMAT_XYUV8888:
1854 case DRM_FORMAT_P010:
1855 case DRM_FORMAT_P012:
1856 case DRM_FORMAT_P016:
1857 if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
1860 case DRM_FORMAT_RGB565:
1861 case DRM_FORMAT_XRGB2101010:
1862 case DRM_FORMAT_XBGR2101010:
1863 case DRM_FORMAT_ARGB2101010:
1864 case DRM_FORMAT_ABGR2101010:
1865 case DRM_FORMAT_XVYU2101010:
1867 case DRM_FORMAT_XBGR16161616F:
1868 case DRM_FORMAT_ABGR16161616F:
1869 case DRM_FORMAT_XRGB16161616F:
1870 case DRM_FORMAT_ARGB16161616F:
1871 case DRM_FORMAT_Y210:
1872 case DRM_FORMAT_Y212:
1873 case DRM_FORMAT_Y216:
1874 case DRM_FORMAT_XVYU12_16161616:
1875 case DRM_FORMAT_XVYU16161616:
1876 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1877 modifier == I915_FORMAT_MOD_X_TILED ||
1878 modifier == I915_FORMAT_MOD_Y_TILED)
1886 static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
1887 enum plane_id plane_id)
1889 if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
1890 return gen12_plane_format_modifiers_mc_ccs;
1892 return gen12_plane_format_modifiers_rc_ccs;
1895 static const struct drm_plane_funcs skl_plane_funcs = {
1896 .update_plane = drm_atomic_helper_update_plane,
1897 .disable_plane = drm_atomic_helper_disable_plane,
1898 .destroy = intel_plane_destroy,
1899 .atomic_duplicate_state = intel_plane_duplicate_state,
1900 .atomic_destroy_state = intel_plane_destroy_state,
1901 .format_mod_supported = skl_plane_format_mod_supported,
1904 static const struct drm_plane_funcs gen12_plane_funcs = {
1905 .update_plane = drm_atomic_helper_update_plane,
1906 .disable_plane = drm_atomic_helper_disable_plane,
1907 .destroy = intel_plane_destroy,
1908 .atomic_duplicate_state = intel_plane_duplicate_state,
1909 .atomic_destroy_state = intel_plane_destroy_state,
1910 .format_mod_supported = gen12_plane_format_mod_supported,
1914 skl_plane_enable_flip_done(struct intel_plane *plane)
1916 struct drm_i915_private *i915 = to_i915(plane->base.dev);
1917 enum pipe pipe = plane->pipe;
1919 spin_lock_irq(&i915->irq_lock);
1920 bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
1921 spin_unlock_irq(&i915->irq_lock);
1925 skl_plane_disable_flip_done(struct intel_plane *plane)
1927 struct drm_i915_private *i915 = to_i915(plane->base.dev);
1928 enum pipe pipe = plane->pipe;
1930 spin_lock_irq(&i915->irq_lock);
1931 bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
1932 spin_unlock_irq(&i915->irq_lock);
1935 struct intel_plane *
1936 skl_universal_plane_create(struct drm_i915_private *dev_priv,
1937 enum pipe pipe, enum plane_id plane_id)
1939 const struct drm_plane_funcs *plane_funcs;
1940 struct intel_plane *plane;
1941 enum drm_plane_type plane_type;
1942 unsigned int supported_rotations;
1943 unsigned int supported_csc;
1944 const u64 *modifiers;
1949 plane = intel_plane_alloc();
1954 plane->id = plane_id;
1955 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
1957 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
1958 if (plane->has_fbc) {
1959 struct intel_fbc *fbc = &dev_priv->fbc;
1961 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
1964 if (DISPLAY_VER(dev_priv) >= 11) {
1965 plane->min_width = icl_plane_min_width;
1966 plane->max_width = icl_plane_max_width;
1967 plane->max_height = icl_plane_max_height;
1968 } else if (DISPLAY_VER(dev_priv) >= 10) {
1969 plane->max_width = glk_plane_max_width;
1970 plane->max_height = skl_plane_max_height;
1972 plane->max_width = skl_plane_max_width;
1973 plane->max_height = skl_plane_max_height;
1976 plane->max_stride = skl_plane_max_stride;
1977 plane->update_plane = skl_update_plane;
1978 plane->disable_plane = skl_disable_plane;
1979 plane->get_hw_state = skl_plane_get_hw_state;
1980 plane->check_plane = skl_plane_check;
1981 plane->min_cdclk = skl_plane_min_cdclk;
1983 if (plane_id == PLANE_PRIMARY) {
1984 plane->need_async_flip_disable_wa = IS_DISPLAY_RANGE(dev_priv,
1986 plane->async_flip = skl_plane_async_flip;
1987 plane->enable_flip_done = skl_plane_enable_flip_done;
1988 plane->disable_flip_done = skl_plane_disable_flip_done;
1991 if (DISPLAY_VER(dev_priv) >= 11)
1992 formats = icl_get_plane_formats(dev_priv, pipe,
1993 plane_id, &num_formats);
1994 else if (DISPLAY_VER(dev_priv) >= 10)
1995 formats = glk_get_plane_formats(dev_priv, pipe,
1996 plane_id, &num_formats);
1998 formats = skl_get_plane_formats(dev_priv, pipe,
1999 plane_id, &num_formats);
2001 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2002 if (DISPLAY_VER(dev_priv) >= 12) {
2003 modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
2004 plane_funcs = &gen12_plane_funcs;
2007 modifiers = skl_plane_format_modifiers_ccs;
2009 modifiers = skl_plane_format_modifiers_noccs;
2010 plane_funcs = &skl_plane_funcs;
2013 if (plane_id == PLANE_PRIMARY)
2014 plane_type = DRM_PLANE_TYPE_PRIMARY;
2016 plane_type = DRM_PLANE_TYPE_OVERLAY;
2018 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2020 formats, num_formats, modifiers,
2022 "plane %d%c", plane_id + 1,
2027 supported_rotations =
2028 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2029 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2031 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
2032 supported_rotations |= DRM_MODE_REFLECT_X;
2034 drm_plane_create_rotation_property(&plane->base,
2036 supported_rotations);
2038 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2040 if (DISPLAY_VER(dev_priv) >= 10)
2041 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2043 drm_plane_create_color_properties(&plane->base,
2045 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2046 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2047 DRM_COLOR_YCBCR_BT709,
2048 DRM_COLOR_YCBCR_LIMITED_RANGE);
2050 drm_plane_create_alpha_property(&plane->base);
2051 drm_plane_create_blend_mode_property(&plane->base,
2052 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2053 BIT(DRM_MODE_BLEND_PREMULTI) |
2054 BIT(DRM_MODE_BLEND_COVERAGE));
2056 drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2058 if (DISPLAY_VER(dev_priv) >= 12)
2059 drm_plane_enable_fb_damage_clips(&plane->base);
2061 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
2062 drm_plane_create_scaling_filter_property(&plane->base,
2063 BIT(DRM_SCALING_FILTER_DEFAULT) |
2064 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2066 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2071 intel_plane_free(plane);
2073 return ERR_PTR(ret);
2077 skl_get_initial_plane_config(struct intel_crtc *crtc,
2078 struct intel_initial_plane_config *plane_config)
2080 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2081 struct drm_device *dev = crtc->base.dev;
2082 struct drm_i915_private *dev_priv = to_i915(dev);
2083 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2084 enum plane_id plane_id = plane->id;
2086 u32 val, base, offset, stride_mult, tiling, alpha;
2087 int fourcc, pixel_format;
2088 unsigned int aligned_height;
2089 struct drm_framebuffer *fb;
2090 struct intel_framebuffer *intel_fb;
2092 if (!plane->get_hw_state(plane, &pipe))
2095 drm_WARN_ON(dev, pipe != crtc->pipe);
2097 if (crtc_state->bigjoiner) {
2098 drm_dbg_kms(&dev_priv->drm,
2099 "Unsupported bigjoiner configuration for initial FB\n");
2103 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2105 drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2109 fb = &intel_fb->base;
2113 val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2115 if (DISPLAY_VER(dev_priv) >= 11)
2116 pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
2118 pixel_format = val & PLANE_CTL_FORMAT_MASK;
2120 if (DISPLAY_VER(dev_priv) >= 10) {
2121 alpha = intel_de_read(dev_priv,
2122 PLANE_COLOR_CTL(pipe, plane_id));
2123 alpha &= PLANE_COLOR_ALPHA_MASK;
2125 alpha = val & PLANE_CTL_ALPHA_MASK;
2128 fourcc = skl_format_to_fourcc(pixel_format,
2129 val & PLANE_CTL_ORDER_RGBX, alpha);
2130 fb->format = drm_format_info(fourcc);
2132 tiling = val & PLANE_CTL_TILED_MASK;
2134 case PLANE_CTL_TILED_LINEAR:
2135 fb->modifier = DRM_FORMAT_MOD_LINEAR;
2137 case PLANE_CTL_TILED_X:
2138 plane_config->tiling = I915_TILING_X;
2139 fb->modifier = I915_FORMAT_MOD_X_TILED;
2141 case PLANE_CTL_TILED_Y:
2142 plane_config->tiling = I915_TILING_Y;
2143 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2144 fb->modifier = DISPLAY_VER(dev_priv) >= 12 ?
2145 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
2146 I915_FORMAT_MOD_Y_TILED_CCS;
2147 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2148 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2150 fb->modifier = I915_FORMAT_MOD_Y_TILED;
2152 case PLANE_CTL_TILED_YF:
2153 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2154 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2156 fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2159 MISSING_CASE(tiling);
2164 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2165 * while i915 HW rotation is clockwise, thats why this swapping.
2167 switch (val & PLANE_CTL_ROTATE_MASK) {
2168 case PLANE_CTL_ROTATE_0:
2169 plane_config->rotation = DRM_MODE_ROTATE_0;
2171 case PLANE_CTL_ROTATE_90:
2172 plane_config->rotation = DRM_MODE_ROTATE_270;
2174 case PLANE_CTL_ROTATE_180:
2175 plane_config->rotation = DRM_MODE_ROTATE_180;
2177 case PLANE_CTL_ROTATE_270:
2178 plane_config->rotation = DRM_MODE_ROTATE_90;
2182 if ((DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) && val & PLANE_CTL_FLIP_HORIZONTAL)
2183 plane_config->rotation |= DRM_MODE_REFLECT_X;
2185 /* 90/270 degree rotation would require extra work */
2186 if (drm_rotation_90_or_270(plane_config->rotation))
2189 base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
2190 plane_config->base = base;
2192 offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2194 val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2195 fb->height = ((val >> 16) & 0xffff) + 1;
2196 fb->width = ((val >> 0) & 0xffff) + 1;
2198 val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2199 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2200 fb->pitches[0] = (val & 0x3ff) * stride_mult;
2202 aligned_height = intel_fb_align_height(fb, 0, fb->height);
2204 plane_config->size = fb->pitches[0] * aligned_height;
2206 drm_dbg_kms(&dev_priv->drm,
2207 "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2208 crtc->base.name, plane->base.name, fb->width, fb->height,
2209 fb->format->cpp[0] * 8, base, fb->pitches[0],
2210 plane_config->size);
2212 plane_config->fb = intel_fb;