]> Git Repo - linux.git/blob - drivers/gpu/drm/i915/display/skl_universal_plane.c
Linux 6.14-rc3
[linux.git] / drivers / gpu / drm / i915 / display / skl_universal_plane.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2020 Intel Corporation
4  */
5
6 #include <drm/drm_atomic_helper.h>
7 #include <drm/drm_blend.h>
8 #include <drm/drm_damage_helper.h>
9 #include <drm/drm_fourcc.h>
10
11 #include "i915_drv.h"
12 #include "i915_reg.h"
13 #include "intel_atomic_plane.h"
14 #include "intel_bo.h"
15 #include "intel_de.h"
16 #include "intel_display_irq.h"
17 #include "intel_display_types.h"
18 #include "intel_dpt.h"
19 #include "intel_fb.h"
20 #include "intel_fbc.h"
21 #include "intel_frontbuffer.h"
22 #include "intel_psr.h"
23 #include "intel_psr_regs.h"
24 #include "skl_scaler.h"
25 #include "skl_universal_plane.h"
26 #include "skl_universal_plane_regs.h"
27 #include "skl_watermark.h"
28 #include "pxp/intel_pxp.h"
29
30 static const u32 skl_plane_formats[] = {
31         DRM_FORMAT_C8,
32         DRM_FORMAT_RGB565,
33         DRM_FORMAT_XRGB8888,
34         DRM_FORMAT_XBGR8888,
35         DRM_FORMAT_ARGB8888,
36         DRM_FORMAT_ABGR8888,
37         DRM_FORMAT_XRGB2101010,
38         DRM_FORMAT_XBGR2101010,
39         DRM_FORMAT_XRGB16161616F,
40         DRM_FORMAT_XBGR16161616F,
41         DRM_FORMAT_YUYV,
42         DRM_FORMAT_YVYU,
43         DRM_FORMAT_UYVY,
44         DRM_FORMAT_VYUY,
45         DRM_FORMAT_XYUV8888,
46 };
47
48 static const u32 skl_planar_formats[] = {
49         DRM_FORMAT_C8,
50         DRM_FORMAT_RGB565,
51         DRM_FORMAT_XRGB8888,
52         DRM_FORMAT_XBGR8888,
53         DRM_FORMAT_ARGB8888,
54         DRM_FORMAT_ABGR8888,
55         DRM_FORMAT_XRGB2101010,
56         DRM_FORMAT_XBGR2101010,
57         DRM_FORMAT_XRGB16161616F,
58         DRM_FORMAT_XBGR16161616F,
59         DRM_FORMAT_YUYV,
60         DRM_FORMAT_YVYU,
61         DRM_FORMAT_UYVY,
62         DRM_FORMAT_VYUY,
63         DRM_FORMAT_NV12,
64         DRM_FORMAT_XYUV8888,
65 };
66
67 static const u32 glk_planar_formats[] = {
68         DRM_FORMAT_C8,
69         DRM_FORMAT_RGB565,
70         DRM_FORMAT_XRGB8888,
71         DRM_FORMAT_XBGR8888,
72         DRM_FORMAT_ARGB8888,
73         DRM_FORMAT_ABGR8888,
74         DRM_FORMAT_XRGB2101010,
75         DRM_FORMAT_XBGR2101010,
76         DRM_FORMAT_XRGB16161616F,
77         DRM_FORMAT_XBGR16161616F,
78         DRM_FORMAT_YUYV,
79         DRM_FORMAT_YVYU,
80         DRM_FORMAT_UYVY,
81         DRM_FORMAT_VYUY,
82         DRM_FORMAT_NV12,
83         DRM_FORMAT_XYUV8888,
84         DRM_FORMAT_P010,
85         DRM_FORMAT_P012,
86         DRM_FORMAT_P016,
87 };
88
89 static const u32 icl_sdr_y_plane_formats[] = {
90         DRM_FORMAT_C8,
91         DRM_FORMAT_RGB565,
92         DRM_FORMAT_XRGB8888,
93         DRM_FORMAT_XBGR8888,
94         DRM_FORMAT_ARGB8888,
95         DRM_FORMAT_ABGR8888,
96         DRM_FORMAT_XRGB2101010,
97         DRM_FORMAT_XBGR2101010,
98         DRM_FORMAT_ARGB2101010,
99         DRM_FORMAT_ABGR2101010,
100         DRM_FORMAT_YUYV,
101         DRM_FORMAT_YVYU,
102         DRM_FORMAT_UYVY,
103         DRM_FORMAT_VYUY,
104         DRM_FORMAT_Y210,
105         DRM_FORMAT_Y212,
106         DRM_FORMAT_Y216,
107         DRM_FORMAT_XYUV8888,
108         DRM_FORMAT_XVYU2101010,
109 };
110
111 static const u32 icl_sdr_uv_plane_formats[] = {
112         DRM_FORMAT_C8,
113         DRM_FORMAT_RGB565,
114         DRM_FORMAT_XRGB8888,
115         DRM_FORMAT_XBGR8888,
116         DRM_FORMAT_ARGB8888,
117         DRM_FORMAT_ABGR8888,
118         DRM_FORMAT_XRGB2101010,
119         DRM_FORMAT_XBGR2101010,
120         DRM_FORMAT_ARGB2101010,
121         DRM_FORMAT_ABGR2101010,
122         DRM_FORMAT_YUYV,
123         DRM_FORMAT_YVYU,
124         DRM_FORMAT_UYVY,
125         DRM_FORMAT_VYUY,
126         DRM_FORMAT_NV12,
127         DRM_FORMAT_P010,
128         DRM_FORMAT_P012,
129         DRM_FORMAT_P016,
130         DRM_FORMAT_Y210,
131         DRM_FORMAT_Y212,
132         DRM_FORMAT_Y216,
133         DRM_FORMAT_XYUV8888,
134         DRM_FORMAT_XVYU2101010,
135 };
136
137 static const u32 icl_hdr_plane_formats[] = {
138         DRM_FORMAT_C8,
139         DRM_FORMAT_RGB565,
140         DRM_FORMAT_XRGB8888,
141         DRM_FORMAT_XBGR8888,
142         DRM_FORMAT_ARGB8888,
143         DRM_FORMAT_ABGR8888,
144         DRM_FORMAT_XRGB2101010,
145         DRM_FORMAT_XBGR2101010,
146         DRM_FORMAT_ARGB2101010,
147         DRM_FORMAT_ABGR2101010,
148         DRM_FORMAT_XRGB16161616F,
149         DRM_FORMAT_XBGR16161616F,
150         DRM_FORMAT_ARGB16161616F,
151         DRM_FORMAT_ABGR16161616F,
152         DRM_FORMAT_YUYV,
153         DRM_FORMAT_YVYU,
154         DRM_FORMAT_UYVY,
155         DRM_FORMAT_VYUY,
156         DRM_FORMAT_NV12,
157         DRM_FORMAT_P010,
158         DRM_FORMAT_P012,
159         DRM_FORMAT_P016,
160         DRM_FORMAT_Y210,
161         DRM_FORMAT_Y212,
162         DRM_FORMAT_Y216,
163         DRM_FORMAT_XYUV8888,
164         DRM_FORMAT_XVYU2101010,
165         DRM_FORMAT_XVYU12_16161616,
166         DRM_FORMAT_XVYU16161616,
167 };
168
169 int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
170 {
171         switch (format) {
172         case PLANE_CTL_FORMAT_RGB_565:
173                 return DRM_FORMAT_RGB565;
174         case PLANE_CTL_FORMAT_NV12:
175                 return DRM_FORMAT_NV12;
176         case PLANE_CTL_FORMAT_XYUV:
177                 return DRM_FORMAT_XYUV8888;
178         case PLANE_CTL_FORMAT_P010:
179                 return DRM_FORMAT_P010;
180         case PLANE_CTL_FORMAT_P012:
181                 return DRM_FORMAT_P012;
182         case PLANE_CTL_FORMAT_P016:
183                 return DRM_FORMAT_P016;
184         case PLANE_CTL_FORMAT_Y210:
185                 return DRM_FORMAT_Y210;
186         case PLANE_CTL_FORMAT_Y212:
187                 return DRM_FORMAT_Y212;
188         case PLANE_CTL_FORMAT_Y216:
189                 return DRM_FORMAT_Y216;
190         case PLANE_CTL_FORMAT_Y410:
191                 return DRM_FORMAT_XVYU2101010;
192         case PLANE_CTL_FORMAT_Y412:
193                 return DRM_FORMAT_XVYU12_16161616;
194         case PLANE_CTL_FORMAT_Y416:
195                 return DRM_FORMAT_XVYU16161616;
196         default:
197         case PLANE_CTL_FORMAT_XRGB_8888:
198                 if (rgb_order) {
199                         if (alpha)
200                                 return DRM_FORMAT_ABGR8888;
201                         else
202                                 return DRM_FORMAT_XBGR8888;
203                 } else {
204                         if (alpha)
205                                 return DRM_FORMAT_ARGB8888;
206                         else
207                                 return DRM_FORMAT_XRGB8888;
208                 }
209         case PLANE_CTL_FORMAT_XRGB_2101010:
210                 if (rgb_order) {
211                         if (alpha)
212                                 return DRM_FORMAT_ABGR2101010;
213                         else
214                                 return DRM_FORMAT_XBGR2101010;
215                 } else {
216                         if (alpha)
217                                 return DRM_FORMAT_ARGB2101010;
218                         else
219                                 return DRM_FORMAT_XRGB2101010;
220                 }
221         case PLANE_CTL_FORMAT_XRGB_16161616F:
222                 if (rgb_order) {
223                         if (alpha)
224                                 return DRM_FORMAT_ABGR16161616F;
225                         else
226                                 return DRM_FORMAT_XBGR16161616F;
227                 } else {
228                         if (alpha)
229                                 return DRM_FORMAT_ARGB16161616F;
230                         else
231                                 return DRM_FORMAT_XRGB16161616F;
232                 }
233         }
234 }
235
236 static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
237 {
238         struct intel_display *display = &i915->display;
239
240         if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display))
241                 return BIT(PLANE_4) | BIT(PLANE_5);
242         else
243                 return BIT(PLANE_6) | BIT(PLANE_7);
244 }
245
246 bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
247                          enum plane_id plane_id)
248 {
249         return DISPLAY_VER(dev_priv) >= 11 &&
250                 icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
251 }
252
253 u8 icl_hdr_plane_mask(void)
254 {
255         return BIT(PLANE_1) | BIT(PLANE_2) | BIT(PLANE_3);
256 }
257
258 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
259 {
260         return DISPLAY_VER(dev_priv) >= 11 &&
261                 icl_hdr_plane_mask() & BIT(plane_id);
262 }
263
264 static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
265                                const struct intel_plane_state *plane_state)
266 {
267         unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
268
269         /* two pixels per clock */
270         return DIV_ROUND_UP(pixel_rate, 2);
271 }
272
273 static void
274 glk_plane_ratio(const struct intel_plane_state *plane_state,
275                 unsigned int *num, unsigned int *den)
276 {
277         const struct drm_framebuffer *fb = plane_state->hw.fb;
278
279         if (fb->format->cpp[0] == 8) {
280                 *num = 10;
281                 *den = 8;
282         } else {
283                 *num = 1;
284                 *den = 1;
285         }
286 }
287
288 static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
289                                const struct intel_plane_state *plane_state)
290 {
291         unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
292         unsigned int num, den;
293
294         glk_plane_ratio(plane_state, &num, &den);
295
296         /* two pixels per clock */
297         return DIV_ROUND_UP(pixel_rate * num, 2 * den);
298 }
299
300 static void
301 skl_plane_ratio(const struct intel_plane_state *plane_state,
302                 unsigned int *num, unsigned int *den)
303 {
304         const struct drm_framebuffer *fb = plane_state->hw.fb;
305
306         if (fb->format->cpp[0] == 8) {
307                 *num = 9;
308                 *den = 8;
309         } else {
310                 *num = 1;
311                 *den = 1;
312         }
313 }
314
315 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
316                                const struct intel_plane_state *plane_state)
317 {
318         unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
319         unsigned int num, den;
320
321         skl_plane_ratio(plane_state, &num, &den);
322
323         return DIV_ROUND_UP(pixel_rate * num, den);
324 }
325
326 static int skl_plane_max_width(const struct drm_framebuffer *fb,
327                                int color_plane,
328                                unsigned int rotation)
329 {
330         int cpp = fb->format->cpp[color_plane];
331
332         switch (fb->modifier) {
333         case DRM_FORMAT_MOD_LINEAR:
334         case I915_FORMAT_MOD_X_TILED:
335                 /*
336                  * Validated limit is 4k, but has 5k should
337                  * work apart from the following features:
338                  * - Ytile (already limited to 4k)
339                  * - FP16 (already limited to 4k)
340                  * - render compression (already limited to 4k)
341                  * - KVMR sprite and cursor (don't care)
342                  * - horizontal panning (TODO verify this)
343                  * - pipe and plane scaling (TODO verify this)
344                  */
345                 if (cpp == 8)
346                         return 4096;
347                 else
348                         return 5120;
349         case I915_FORMAT_MOD_Y_TILED_CCS:
350         case I915_FORMAT_MOD_Yf_TILED_CCS:
351                 /* FIXME AUX plane? */
352         case I915_FORMAT_MOD_Y_TILED:
353         case I915_FORMAT_MOD_Yf_TILED:
354                 if (cpp == 8)
355                         return 2048;
356                 else
357                         return 4096;
358         default:
359                 MISSING_CASE(fb->modifier);
360                 return 2048;
361         }
362 }
363
364 static int glk_plane_max_width(const struct drm_framebuffer *fb,
365                                int color_plane,
366                                unsigned int rotation)
367 {
368         int cpp = fb->format->cpp[color_plane];
369
370         switch (fb->modifier) {
371         case DRM_FORMAT_MOD_LINEAR:
372         case I915_FORMAT_MOD_X_TILED:
373                 if (cpp == 8)
374                         return 4096;
375                 else
376                         return 5120;
377         case I915_FORMAT_MOD_Y_TILED_CCS:
378         case I915_FORMAT_MOD_Yf_TILED_CCS:
379                 /* FIXME AUX plane? */
380         case I915_FORMAT_MOD_Y_TILED:
381         case I915_FORMAT_MOD_Yf_TILED:
382                 if (cpp == 8)
383                         return 2048;
384                 else
385                         return 5120;
386         default:
387                 MISSING_CASE(fb->modifier);
388                 return 2048;
389         }
390 }
391
392 static int icl_plane_min_width(const struct drm_framebuffer *fb,
393                                int color_plane,
394                                unsigned int rotation)
395 {
396         /* Wa_14011264657, Wa_14011050563: gen11+ */
397         switch (fb->format->format) {
398         case DRM_FORMAT_C8:
399                 return 18;
400         case DRM_FORMAT_RGB565:
401                 return 10;
402         case DRM_FORMAT_XRGB8888:
403         case DRM_FORMAT_XBGR8888:
404         case DRM_FORMAT_ARGB8888:
405         case DRM_FORMAT_ABGR8888:
406         case DRM_FORMAT_XRGB2101010:
407         case DRM_FORMAT_XBGR2101010:
408         case DRM_FORMAT_ARGB2101010:
409         case DRM_FORMAT_ABGR2101010:
410         case DRM_FORMAT_XVYU2101010:
411         case DRM_FORMAT_Y212:
412         case DRM_FORMAT_Y216:
413                 return 6;
414         case DRM_FORMAT_NV12:
415                 return 20;
416         case DRM_FORMAT_P010:
417         case DRM_FORMAT_P012:
418         case DRM_FORMAT_P016:
419                 return 12;
420         case DRM_FORMAT_XRGB16161616F:
421         case DRM_FORMAT_XBGR16161616F:
422         case DRM_FORMAT_ARGB16161616F:
423         case DRM_FORMAT_ABGR16161616F:
424         case DRM_FORMAT_XVYU12_16161616:
425         case DRM_FORMAT_XVYU16161616:
426                 return 4;
427         default:
428                 return 1;
429         }
430 }
431
432 static int xe3_plane_max_width(const struct drm_framebuffer *fb,
433                                int color_plane,
434                                unsigned int rotation)
435 {
436         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
437                 return 4096;
438         else
439                 return 6144;
440 }
441
442 static int icl_hdr_plane_max_width(const struct drm_framebuffer *fb,
443                                    int color_plane,
444                                    unsigned int rotation)
445 {
446         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
447                 return 4096;
448         else
449                 return 5120;
450 }
451
452 static int icl_sdr_plane_max_width(const struct drm_framebuffer *fb,
453                                    int color_plane,
454                                    unsigned int rotation)
455 {
456         return 5120;
457 }
458
459 static int skl_plane_max_height(const struct drm_framebuffer *fb,
460                                 int color_plane,
461                                 unsigned int rotation)
462 {
463         return 4096;
464 }
465
466 static int icl_plane_max_height(const struct drm_framebuffer *fb,
467                                 int color_plane,
468                                 unsigned int rotation)
469 {
470         return 4320;
471 }
472
473 static unsigned int
474 plane_max_stride(struct intel_plane *plane,
475                  u32 pixel_format, u64 modifier,
476                  unsigned int rotation,
477                  unsigned int max_pixels,
478                  unsigned int max_bytes)
479 {
480         const struct drm_format_info *info = drm_format_info(pixel_format);
481         int cpp = info->cpp[0];
482
483         if (drm_rotation_90_or_270(rotation))
484                 return min(max_pixels, max_bytes / cpp);
485         else
486                 return min(max_pixels * cpp, max_bytes);
487 }
488
489 static unsigned int
490 adl_plane_max_stride(struct intel_plane *plane,
491                      u32 pixel_format, u64 modifier,
492                      unsigned int rotation)
493 {
494         unsigned int max_pixels = 65536; /* PLANE_OFFSET limit */
495         unsigned int max_bytes = 128 * 1024;
496
497         return plane_max_stride(plane, pixel_format,
498                                 modifier, rotation,
499                                 max_pixels, max_bytes);
500 }
501
502 static unsigned int
503 skl_plane_max_stride(struct intel_plane *plane,
504                      u32 pixel_format, u64 modifier,
505                      unsigned int rotation)
506 {
507         unsigned int max_pixels = 8192; /* PLANE_OFFSET limit */
508         unsigned int max_bytes = 32 * 1024;
509
510         return plane_max_stride(plane, pixel_format,
511                                 modifier, rotation,
512                                 max_pixels, max_bytes);
513 }
514
515 static u32 tgl_plane_min_alignment(struct intel_plane *plane,
516                                    const struct drm_framebuffer *fb,
517                                    int color_plane)
518 {
519         struct drm_i915_private *i915 = to_i915(plane->base.dev);
520         /* PLANE_SURF GGTT -> DPT alignment */
521         int mult = intel_fb_uses_dpt(fb) ? 512 : 1;
522
523         /* AUX_DIST needs only 4K alignment */
524         if (intel_fb_is_ccs_aux_plane(fb, color_plane))
525                 return mult * 4 * 1024;
526
527         switch (fb->modifier) {
528         case DRM_FORMAT_MOD_LINEAR:
529         case I915_FORMAT_MOD_X_TILED:
530         case I915_FORMAT_MOD_Y_TILED:
531         case I915_FORMAT_MOD_4_TILED:
532                 /*
533                  * FIXME ADL sees GGTT/DMAR faults with async
534                  * flips unless we align to 16k at least.
535                  * Figure out what's going on here...
536                  */
537                 if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915))
538                         return mult * 16 * 1024;
539                 return mult * 4 * 1024;
540         case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
541         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
542         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
543         case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
544         case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
545         case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
546         case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
547         case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
548         case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
549         case I915_FORMAT_MOD_4_TILED_BMG_CCS:
550         case I915_FORMAT_MOD_4_TILED_LNL_CCS:
551                 /*
552                  * Align to at least 4x1 main surface
553                  * tiles (16K) to match 64B of AUX.
554                  */
555                 return max(mult * 4 * 1024, 16 * 1024);
556         default:
557                 MISSING_CASE(fb->modifier);
558                 return 0;
559         }
560 }
561
562 static u32 skl_plane_min_alignment(struct intel_plane *plane,
563                                    const struct drm_framebuffer *fb,
564                                    int color_plane)
565 {
566         /*
567          * AUX_DIST needs only 4K alignment,
568          * as does ICL UV PLANE_SURF.
569          */
570         if (color_plane != 0)
571                 return 4 * 1024;
572
573         switch (fb->modifier) {
574         case DRM_FORMAT_MOD_LINEAR:
575         case I915_FORMAT_MOD_X_TILED:
576                 return 256 * 1024;
577         case I915_FORMAT_MOD_Y_TILED_CCS:
578         case I915_FORMAT_MOD_Yf_TILED_CCS:
579         case I915_FORMAT_MOD_Y_TILED:
580         case I915_FORMAT_MOD_Yf_TILED:
581                 return 1 * 1024 * 1024;
582         default:
583                 MISSING_CASE(fb->modifier);
584                 return 0;
585         }
586 }
587
588 /* Preoffset values for YUV to RGB Conversion */
589 #define PREOFF_YUV_TO_RGB_HI            0x1800
590 #define PREOFF_YUV_TO_RGB_ME            0x0000
591 #define PREOFF_YUV_TO_RGB_LO            0x1800
592
593 #define  ROFF(x)          (((x) & 0xffff) << 16)
594 #define  GOFF(x)          (((x) & 0xffff) << 0)
595 #define  BOFF(x)          (((x) & 0xffff) << 16)
596
597 /*
598  * Programs the input color space conversion stage for ICL HDR planes.
599  * Note that it is assumed that this stage always happens after YUV
600  * range correction. Thus, the input to this stage is assumed to be
601  * in full-range YCbCr.
602  */
603 static void
604 icl_program_input_csc(struct intel_dsb *dsb,
605                       struct intel_plane *plane,
606                       const struct intel_plane_state *plane_state)
607 {
608         struct intel_display *display = to_intel_display(plane->base.dev);
609         enum pipe pipe = plane->pipe;
610         enum plane_id plane_id = plane->id;
611
612         static const u16 input_csc_matrix[][9] = {
613                 /*
614                  * BT.601 full range YCbCr -> full range RGB
615                  * The matrix required is :
616                  * [1.000, 0.000, 1.371,
617                  *  1.000, -0.336, -0.698,
618                  *  1.000, 1.732, 0.0000]
619                  */
620                 [DRM_COLOR_YCBCR_BT601] = {
621                         0x7AF8, 0x7800, 0x0,
622                         0x8B28, 0x7800, 0x9AC0,
623                         0x0, 0x7800, 0x7DD8,
624                 },
625                 /*
626                  * BT.709 full range YCbCr -> full range RGB
627                  * The matrix required is :
628                  * [1.000, 0.000, 1.574,
629                  *  1.000, -0.187, -0.468,
630                  *  1.000, 1.855, 0.0000]
631                  */
632                 [DRM_COLOR_YCBCR_BT709] = {
633                         0x7C98, 0x7800, 0x0,
634                         0x9EF8, 0x7800, 0xAC00,
635                         0x0, 0x7800,  0x7ED8,
636                 },
637                 /*
638                  * BT.2020 full range YCbCr -> full range RGB
639                  * The matrix required is :
640                  * [1.000, 0.000, 1.474,
641                  *  1.000, -0.1645, -0.5713,
642                  *  1.000, 1.8814, 0.0000]
643                  */
644                 [DRM_COLOR_YCBCR_BT2020] = {
645                         0x7BC8, 0x7800, 0x0,
646                         0x8928, 0x7800, 0xAA88,
647                         0x0, 0x7800, 0x7F10,
648                 },
649         };
650         const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
651
652         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
653                            ROFF(csc[0]) | GOFF(csc[1]));
654         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
655                            BOFF(csc[2]));
656         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
657                            ROFF(csc[3]) | GOFF(csc[4]));
658         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
659                            BOFF(csc[5]));
660         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
661                            ROFF(csc[6]) | GOFF(csc[7]));
662         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
663                            BOFF(csc[8]));
664
665         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
666                            PREOFF_YUV_TO_RGB_HI);
667         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
668                            PREOFF_YUV_TO_RGB_ME);
669         intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
670                            PREOFF_YUV_TO_RGB_LO);
671         intel_de_write_dsb(display, dsb,
672                            PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
673         intel_de_write_dsb(display, dsb,
674                            PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
675         intel_de_write_dsb(display, dsb,
676                            PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
677 }
678
679 static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
680                                           int color_plane, unsigned int rotation)
681 {
682         /*
683          * The stride is either expressed as a multiple of 64 bytes chunks for
684          * linear buffers or in number of tiles for tiled buffers.
685          */
686         if (is_surface_linear(fb, color_plane))
687                 return 64;
688         else if (drm_rotation_90_or_270(rotation))
689                 return intel_tile_height(fb, color_plane);
690         else
691                 return intel_tile_width_bytes(fb, color_plane);
692 }
693
694 static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
695                             int color_plane)
696 {
697         const struct drm_framebuffer *fb = plane_state->hw.fb;
698         unsigned int rotation = plane_state->hw.rotation;
699         u32 stride = plane_state->view.color_plane[color_plane].scanout_stride;
700
701         if (color_plane >= fb->format->num_planes)
702                 return 0;
703
704         return stride / skl_plane_stride_mult(fb, color_plane, rotation);
705 }
706
707 static u32 skl_plane_ddb_reg_val(const struct skl_ddb_entry *entry)
708 {
709         if (!entry->end)
710                 return 0;
711
712         return PLANE_BUF_END(entry->end - 1) |
713                 PLANE_BUF_START(entry->start);
714 }
715
716 static u32 xe3_plane_min_ddb_reg_val(const u16 *min_ddb,
717                                      const u16 *interim_ddb)
718 {
719         u32 val = 0;
720
721         if (*min_ddb)
722                 val |= PLANE_MIN_DBUF_BLOCKS(*min_ddb);
723
724         if (*interim_ddb)
725                 val |= PLANE_INTERIM_DBUF_BLOCKS(*interim_ddb);
726
727         val |= val ? PLANE_AUTO_MIN_DBUF_EN : 0;
728
729         return val;
730 }
731
732 static u32 skl_plane_wm_reg_val(const struct skl_wm_level *level)
733 {
734         u32 val = 0;
735
736         if (level->enable)
737                 val |= PLANE_WM_EN;
738         if (level->ignore_lines)
739                 val |= PLANE_WM_IGNORE_LINES;
740         if (level->auto_min_alloc_wm_enable)
741                 val |= PLANE_WM_AUTO_MIN_ALLOC_EN;
742
743         val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks);
744         val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines);
745
746         return val;
747 }
748
749 static void skl_write_plane_wm(struct intel_dsb *dsb,
750                                struct intel_plane *plane,
751                                const struct intel_crtc_state *crtc_state)
752 {
753         struct intel_display *display = to_intel_display(plane->base.dev);
754         enum plane_id plane_id = plane->id;
755         enum pipe pipe = plane->pipe;
756         const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
757         const struct skl_ddb_entry *ddb =
758                 &crtc_state->wm.skl.plane_ddb[plane_id];
759         const struct skl_ddb_entry *ddb_y =
760                 &crtc_state->wm.skl.plane_ddb_y[plane_id];
761         const u16 *min_ddb = &crtc_state->wm.skl.plane_min_ddb[plane_id];
762         const u16 *interim_ddb =
763                 &crtc_state->wm.skl.plane_interim_ddb[plane_id];
764         int level;
765
766         for (level = 0; level < display->wm.num_levels; level++)
767                 intel_de_write_dsb(display, dsb, PLANE_WM(pipe, plane_id, level),
768                                    skl_plane_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
769
770         intel_de_write_dsb(display, dsb, PLANE_WM_TRANS(pipe, plane_id),
771                            skl_plane_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
772
773         if (HAS_HW_SAGV_WM(display)) {
774                 const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
775
776                 intel_de_write_dsb(display, dsb, PLANE_WM_SAGV(pipe, plane_id),
777                                    skl_plane_wm_reg_val(&wm->sagv.wm0));
778                 intel_de_write_dsb(display, dsb, PLANE_WM_SAGV_TRANS(pipe, plane_id),
779                                    skl_plane_wm_reg_val(&wm->sagv.trans_wm));
780         }
781
782         intel_de_write_dsb(display, dsb, PLANE_BUF_CFG(pipe, plane_id),
783                            skl_plane_ddb_reg_val(ddb));
784
785         if (DISPLAY_VER(display) < 11)
786                 intel_de_write_dsb(display, dsb, PLANE_NV12_BUF_CFG(pipe, plane_id),
787                                    skl_plane_ddb_reg_val(ddb_y));
788
789         if (DISPLAY_VER(display) >= 30)
790                 intel_de_write_dsb(display, dsb, PLANE_MIN_BUF_CFG(pipe, plane_id),
791                                    xe3_plane_min_ddb_reg_val(min_ddb, interim_ddb));
792 }
793
794 static void
795 skl_plane_disable_arm(struct intel_dsb *dsb,
796                       struct intel_plane *plane,
797                       const struct intel_crtc_state *crtc_state)
798 {
799         struct intel_display *display = to_intel_display(plane->base.dev);
800         enum plane_id plane_id = plane->id;
801         enum pipe pipe = plane->pipe;
802
803         skl_write_plane_wm(dsb, plane, crtc_state);
804
805         intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0);
806         intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0);
807 }
808
809 static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb,
810                                             struct intel_plane *plane,
811                                             const struct intel_crtc_state *crtc_state)
812 {
813         struct intel_display *display = to_intel_display(plane->base.dev);
814         enum pipe pipe = plane->pipe;
815
816         if (!crtc_state->enable_psr2_sel_fetch)
817                 return;
818
819         intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0);
820 }
821
822 static void
823 icl_plane_disable_arm(struct intel_dsb *dsb,
824                       struct intel_plane *plane,
825                       const struct intel_crtc_state *crtc_state)
826 {
827         struct intel_display *display = to_intel_display(plane->base.dev);
828         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
829         enum plane_id plane_id = plane->id;
830         enum pipe pipe = plane->pipe;
831
832         if (icl_is_hdr_plane(dev_priv, plane_id))
833                 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id), 0);
834
835         skl_write_plane_wm(dsb, plane, crtc_state);
836
837         icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state);
838         intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0);
839         intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0);
840 }
841
842 static bool
843 skl_plane_get_hw_state(struct intel_plane *plane,
844                        enum pipe *pipe)
845 {
846         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
847         enum intel_display_power_domain power_domain;
848         enum plane_id plane_id = plane->id;
849         intel_wakeref_t wakeref;
850         bool ret;
851
852         power_domain = POWER_DOMAIN_PIPE(plane->pipe);
853         wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
854         if (!wakeref)
855                 return false;
856
857         ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
858
859         *pipe = plane->pipe;
860
861         intel_display_power_put(dev_priv, power_domain, wakeref);
862
863         return ret;
864 }
865
866 static u32 skl_plane_ctl_format(u32 pixel_format)
867 {
868         switch (pixel_format) {
869         case DRM_FORMAT_C8:
870                 return PLANE_CTL_FORMAT_INDEXED;
871         case DRM_FORMAT_RGB565:
872                 return PLANE_CTL_FORMAT_RGB_565;
873         case DRM_FORMAT_XBGR8888:
874         case DRM_FORMAT_ABGR8888:
875                 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
876         case DRM_FORMAT_XRGB8888:
877         case DRM_FORMAT_ARGB8888:
878                 return PLANE_CTL_FORMAT_XRGB_8888;
879         case DRM_FORMAT_XBGR2101010:
880         case DRM_FORMAT_ABGR2101010:
881                 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
882         case DRM_FORMAT_XRGB2101010:
883         case DRM_FORMAT_ARGB2101010:
884                 return PLANE_CTL_FORMAT_XRGB_2101010;
885         case DRM_FORMAT_XBGR16161616F:
886         case DRM_FORMAT_ABGR16161616F:
887                 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
888         case DRM_FORMAT_XRGB16161616F:
889         case DRM_FORMAT_ARGB16161616F:
890                 return PLANE_CTL_FORMAT_XRGB_16161616F;
891         case DRM_FORMAT_XYUV8888:
892                 return PLANE_CTL_FORMAT_XYUV;
893         case DRM_FORMAT_YUYV:
894                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YUYV;
895         case DRM_FORMAT_YVYU:
896                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YVYU;
897         case DRM_FORMAT_UYVY:
898                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_UYVY;
899         case DRM_FORMAT_VYUY:
900                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_VYUY;
901         case DRM_FORMAT_NV12:
902                 return PLANE_CTL_FORMAT_NV12;
903         case DRM_FORMAT_P010:
904                 return PLANE_CTL_FORMAT_P010;
905         case DRM_FORMAT_P012:
906                 return PLANE_CTL_FORMAT_P012;
907         case DRM_FORMAT_P016:
908                 return PLANE_CTL_FORMAT_P016;
909         case DRM_FORMAT_Y210:
910                 return PLANE_CTL_FORMAT_Y210;
911         case DRM_FORMAT_Y212:
912                 return PLANE_CTL_FORMAT_Y212;
913         case DRM_FORMAT_Y216:
914                 return PLANE_CTL_FORMAT_Y216;
915         case DRM_FORMAT_XVYU2101010:
916                 return PLANE_CTL_FORMAT_Y410;
917         case DRM_FORMAT_XVYU12_16161616:
918                 return PLANE_CTL_FORMAT_Y412;
919         case DRM_FORMAT_XVYU16161616:
920                 return PLANE_CTL_FORMAT_Y416;
921         default:
922                 MISSING_CASE(pixel_format);
923         }
924
925         return 0;
926 }
927
928 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
929 {
930         if (!plane_state->hw.fb->format->has_alpha)
931                 return PLANE_CTL_ALPHA_DISABLE;
932
933         switch (plane_state->hw.pixel_blend_mode) {
934         case DRM_MODE_BLEND_PIXEL_NONE:
935                 return PLANE_CTL_ALPHA_DISABLE;
936         case DRM_MODE_BLEND_PREMULTI:
937                 return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
938         case DRM_MODE_BLEND_COVERAGE:
939                 return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
940         default:
941                 MISSING_CASE(plane_state->hw.pixel_blend_mode);
942                 return PLANE_CTL_ALPHA_DISABLE;
943         }
944 }
945
946 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
947 {
948         if (!plane_state->hw.fb->format->has_alpha)
949                 return PLANE_COLOR_ALPHA_DISABLE;
950
951         switch (plane_state->hw.pixel_blend_mode) {
952         case DRM_MODE_BLEND_PIXEL_NONE:
953                 return PLANE_COLOR_ALPHA_DISABLE;
954         case DRM_MODE_BLEND_PREMULTI:
955                 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
956         case DRM_MODE_BLEND_COVERAGE:
957                 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
958         default:
959                 MISSING_CASE(plane_state->hw.pixel_blend_mode);
960                 return PLANE_COLOR_ALPHA_DISABLE;
961         }
962 }
963
964 static u32 skl_plane_ctl_tiling(u64 fb_modifier)
965 {
966         switch (fb_modifier) {
967         case DRM_FORMAT_MOD_LINEAR:
968                 break;
969         case I915_FORMAT_MOD_X_TILED:
970                 return PLANE_CTL_TILED_X;
971         case I915_FORMAT_MOD_Y_TILED:
972                 return PLANE_CTL_TILED_Y;
973         case I915_FORMAT_MOD_4_TILED:
974                 return PLANE_CTL_TILED_4;
975         case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
976                 return PLANE_CTL_TILED_4 |
977                         PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
978                         PLANE_CTL_CLEAR_COLOR_DISABLE;
979         case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
980                 return PLANE_CTL_TILED_4 |
981                         PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
982                         PLANE_CTL_CLEAR_COLOR_DISABLE;
983         case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
984                 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
985         case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
986                 return PLANE_CTL_TILED_4 |
987                         PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
988                         PLANE_CTL_CLEAR_COLOR_DISABLE;
989         case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
990                 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
991         case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
992                 return PLANE_CTL_TILED_4 | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
993         case I915_FORMAT_MOD_4_TILED_BMG_CCS:
994         case I915_FORMAT_MOD_4_TILED_LNL_CCS:
995                 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
996         case I915_FORMAT_MOD_Y_TILED_CCS:
997         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
998                 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
999         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
1000                 return PLANE_CTL_TILED_Y |
1001                        PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
1002                        PLANE_CTL_CLEAR_COLOR_DISABLE;
1003         case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
1004                 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
1005         case I915_FORMAT_MOD_Yf_TILED:
1006                 return PLANE_CTL_TILED_YF;
1007         case I915_FORMAT_MOD_Yf_TILED_CCS:
1008                 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
1009         default:
1010                 MISSING_CASE(fb_modifier);
1011         }
1012
1013         return 0;
1014 }
1015
1016 static u32 skl_plane_ctl_rotate(unsigned int rotate)
1017 {
1018         switch (rotate) {
1019         case DRM_MODE_ROTATE_0:
1020                 break;
1021         /*
1022          * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
1023          * while i915 HW rotation is clockwise, thats why this swapping.
1024          */
1025         case DRM_MODE_ROTATE_90:
1026                 return PLANE_CTL_ROTATE_270;
1027         case DRM_MODE_ROTATE_180:
1028                 return PLANE_CTL_ROTATE_180;
1029         case DRM_MODE_ROTATE_270:
1030                 return PLANE_CTL_ROTATE_90;
1031         default:
1032                 MISSING_CASE(rotate);
1033         }
1034
1035         return 0;
1036 }
1037
1038 static u32 icl_plane_ctl_flip(unsigned int reflect)
1039 {
1040         switch (reflect) {
1041         case 0:
1042                 break;
1043         case DRM_MODE_REFLECT_X:
1044                 return PLANE_CTL_FLIP_HORIZONTAL;
1045         case DRM_MODE_REFLECT_Y:
1046         default:
1047                 MISSING_CASE(reflect);
1048         }
1049
1050         return 0;
1051 }
1052
1053 static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
1054 {
1055         const struct drm_framebuffer *fb = plane_state->hw.fb;
1056
1057         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
1058                 switch (fb->format->cpp[0]) {
1059                 case 2:
1060                         return PLANE_CTL_ARB_SLOTS(1);
1061                 default:
1062                         return PLANE_CTL_ARB_SLOTS(0);
1063                 }
1064         } else {
1065                 switch (fb->format->cpp[0]) {
1066                 case 8:
1067                         return PLANE_CTL_ARB_SLOTS(3);
1068                 case 4:
1069                         return PLANE_CTL_ARB_SLOTS(1);
1070                 default:
1071                         return PLANE_CTL_ARB_SLOTS(0);
1072                 }
1073         }
1074 }
1075
1076 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
1077 {
1078         struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1079         u32 plane_ctl = 0;
1080
1081         if (DISPLAY_VER(dev_priv) >= 10)
1082                 return plane_ctl;
1083
1084         if (crtc_state->gamma_enable)
1085                 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
1086
1087         if (crtc_state->csc_enable)
1088                 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
1089
1090         return plane_ctl;
1091 }
1092
1093 static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
1094                          const struct intel_plane_state *plane_state)
1095 {
1096         struct drm_i915_private *dev_priv =
1097                 to_i915(plane_state->uapi.plane->dev);
1098         const struct drm_framebuffer *fb = plane_state->hw.fb;
1099         unsigned int rotation = plane_state->hw.rotation;
1100         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1101         u32 plane_ctl;
1102
1103         plane_ctl = PLANE_CTL_ENABLE;
1104
1105         if (DISPLAY_VER(dev_priv) < 10) {
1106                 plane_ctl |= skl_plane_ctl_alpha(plane_state);
1107                 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
1108
1109                 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1110                         plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
1111
1112                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1113                         plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
1114         }
1115
1116         plane_ctl |= skl_plane_ctl_format(fb->format->format);
1117         plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
1118         plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
1119
1120         if (DISPLAY_VER(dev_priv) >= 11)
1121                 plane_ctl |= icl_plane_ctl_flip(rotation &
1122                                                 DRM_MODE_REFLECT_MASK);
1123
1124         if (key->flags & I915_SET_COLORKEY_DESTINATION)
1125                 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
1126         else if (key->flags & I915_SET_COLORKEY_SOURCE)
1127                 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
1128
1129         /* Wa_22012358565:adl-p */
1130         if (DISPLAY_VER(dev_priv) == 13)
1131                 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
1132
1133         return plane_ctl;
1134 }
1135
1136 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
1137 {
1138         struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1139         u32 plane_color_ctl = 0;
1140
1141         if (DISPLAY_VER(dev_priv) >= 11)
1142                 return plane_color_ctl;
1143
1144         if (crtc_state->gamma_enable)
1145                 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
1146
1147         if (crtc_state->csc_enable)
1148                 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
1149
1150         return plane_color_ctl;
1151 }
1152
1153 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
1154                                const struct intel_plane_state *plane_state)
1155 {
1156         struct drm_i915_private *dev_priv =
1157                 to_i915(plane_state->uapi.plane->dev);
1158         const struct drm_framebuffer *fb = plane_state->hw.fb;
1159         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1160         u32 plane_color_ctl = 0;
1161
1162         plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
1163         plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
1164
1165         if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
1166                 switch (plane_state->hw.color_encoding) {
1167                 case DRM_COLOR_YCBCR_BT709:
1168                         plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
1169                         break;
1170                 case DRM_COLOR_YCBCR_BT2020:
1171                         plane_color_ctl |=
1172                                 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
1173                         break;
1174                 default:
1175                         plane_color_ctl |=
1176                                 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
1177                 }
1178                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1179                         plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
1180         } else if (fb->format->is_yuv) {
1181                 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
1182                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1183                         plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
1184         }
1185
1186         if (plane_state->force_black)
1187                 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
1188
1189         return plane_color_ctl;
1190 }
1191
1192 static u32 skl_surf_address(const struct intel_plane_state *plane_state,
1193                             int color_plane)
1194 {
1195         struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1196         const struct drm_framebuffer *fb = plane_state->hw.fb;
1197         u32 offset = plane_state->view.color_plane[color_plane].offset;
1198
1199         if (intel_fb_uses_dpt(fb)) {
1200                 /*
1201                  * The DPT object contains only one vma, so the VMA's offset
1202                  * within the DPT is always 0.
1203                  */
1204                 drm_WARN_ON(&i915->drm, plane_state->dpt_vma &&
1205                             intel_dpt_offset(plane_state->dpt_vma));
1206                 drm_WARN_ON(&i915->drm, offset & 0x1fffff);
1207                 return offset >> 9;
1208         } else {
1209                 drm_WARN_ON(&i915->drm, offset & 0xfff);
1210                 return offset;
1211         }
1212 }
1213
1214 static u32 skl_plane_surf(const struct intel_plane_state *plane_state,
1215                           int color_plane)
1216 {
1217         u32 plane_surf;
1218
1219         plane_surf = intel_plane_ggtt_offset(plane_state) +
1220                 skl_surf_address(plane_state, color_plane);
1221
1222         if (plane_state->decrypt)
1223                 plane_surf |= PLANE_SURF_DECRYPT;
1224
1225         return plane_surf;
1226 }
1227
1228 static u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state,
1229                               int color_plane)
1230 {
1231         struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1232         const struct drm_framebuffer *fb = plane_state->hw.fb;
1233         int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1234         u32 aux_dist;
1235
1236         if (!aux_plane)
1237                 return 0;
1238
1239         aux_dist = skl_surf_address(plane_state, aux_plane) -
1240                 skl_surf_address(plane_state, color_plane);
1241
1242         if (DISPLAY_VER(i915) < 12)
1243                 aux_dist |= PLANE_AUX_STRIDE(skl_plane_stride(plane_state, aux_plane));
1244
1245         return aux_dist;
1246 }
1247
1248 static u32 skl_plane_keyval(const struct intel_plane_state *plane_state)
1249 {
1250         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1251
1252         return key->min_value;
1253 }
1254
1255 static u32 skl_plane_keymax(const struct intel_plane_state *plane_state)
1256 {
1257         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1258         u8 alpha = plane_state->hw.alpha >> 8;
1259
1260         return (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
1261 }
1262
1263 static u32 skl_plane_keymsk(const struct intel_plane_state *plane_state)
1264 {
1265         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1266         u8 alpha = plane_state->hw.alpha >> 8;
1267         u32 keymsk;
1268
1269         keymsk = key->channel_mask & 0x7ffffff;
1270         if (alpha < 0xff)
1271                 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
1272
1273         return keymsk;
1274 }
1275
1276 static void icl_plane_csc_load_black(struct intel_dsb *dsb,
1277                                      struct intel_plane *plane,
1278                                      const struct intel_crtc_state *crtc_state)
1279 {
1280         struct intel_display *display = to_intel_display(plane->base.dev);
1281         enum plane_id plane_id = plane->id;
1282         enum pipe pipe = plane->pipe;
1283
1284         intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 0), 0);
1285         intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 1), 0);
1286
1287         intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 2), 0);
1288         intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 3), 0);
1289
1290         intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 4), 0);
1291         intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 5), 0);
1292
1293         intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0);
1294         intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0);
1295         intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0);
1296
1297         intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0);
1298         intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0);
1299         intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
1300 }
1301
1302 static int icl_plane_color_plane(const struct intel_plane_state *plane_state)
1303 {
1304         /* Program the UV plane on planar master */
1305         if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1306                 return 1;
1307         else
1308                 return 0;
1309 }
1310
1311 static void
1312 skl_plane_update_noarm(struct intel_dsb *dsb,
1313                        struct intel_plane *plane,
1314                        const struct intel_crtc_state *crtc_state,
1315                        const struct intel_plane_state *plane_state)
1316 {
1317         struct intel_display *display = to_intel_display(plane->base.dev);
1318         enum plane_id plane_id = plane->id;
1319         enum pipe pipe = plane->pipe;
1320         u32 stride = skl_plane_stride(plane_state, 0);
1321         int crtc_x = plane_state->uapi.dst.x1;
1322         int crtc_y = plane_state->uapi.dst.y1;
1323         u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1324         u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1325
1326         /* The scaler will handle the output position */
1327         if (plane_state->scaler_id >= 0) {
1328                 crtc_x = 0;
1329                 crtc_y = 0;
1330         }
1331
1332         intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id),
1333                            PLANE_STRIDE_(stride));
1334         intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id),
1335                            PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1336         intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id),
1337                            PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1338
1339         skl_write_plane_wm(dsb, plane, crtc_state);
1340 }
1341
1342 static void
1343 skl_plane_update_arm(struct intel_dsb *dsb,
1344                      struct intel_plane *plane,
1345                      const struct intel_crtc_state *crtc_state,
1346                      const struct intel_plane_state *plane_state)
1347 {
1348         struct intel_display *display = to_intel_display(plane->base.dev);
1349         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1350         enum plane_id plane_id = plane->id;
1351         enum pipe pipe = plane->pipe;
1352         u32 x = plane_state->view.color_plane[0].x;
1353         u32 y = plane_state->view.color_plane[0].y;
1354         u32 plane_ctl, plane_color_ctl = 0;
1355
1356         plane_ctl = plane_state->ctl |
1357                 skl_plane_ctl_crtc(crtc_state);
1358
1359         /* see intel_plane_atomic_calc_changes() */
1360         if (plane->need_async_flip_toggle_wa &&
1361             crtc_state->async_flip_planes & BIT(plane->id))
1362                 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1363
1364         if (DISPLAY_VER(dev_priv) >= 10)
1365                 plane_color_ctl = plane_state->color_ctl |
1366                         glk_plane_color_ctl_crtc(crtc_state);
1367
1368         intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id),
1369                            skl_plane_keyval(plane_state));
1370         intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id),
1371                            skl_plane_keymsk(plane_state));
1372         intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id),
1373                            skl_plane_keymax(plane_state));
1374
1375         intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id),
1376                            PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1377
1378         intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id),
1379                            skl_plane_aux_dist(plane_state, 0));
1380
1381         intel_de_write_dsb(display, dsb, PLANE_AUX_OFFSET(pipe, plane_id),
1382                            PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
1383                            PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
1384
1385         if (DISPLAY_VER(dev_priv) >= 10)
1386                 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id),
1387                                    plane_color_ctl);
1388
1389         /*
1390          * Enable the scaler before the plane so that we don't
1391          * get a catastrophic underrun even if the two operations
1392          * end up happening in two different frames.
1393          *
1394          * TODO: split into noarm+arm pair
1395          */
1396         if (plane_state->scaler_id >= 0)
1397                 skl_program_plane_scaler(plane, crtc_state, plane_state);
1398
1399         /*
1400          * The control register self-arms if the plane was previously
1401          * disabled. Try to make the plane enable atomic by writing
1402          * the control register just before the surface register.
1403          */
1404         intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1405                            plane_ctl);
1406         intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1407                            skl_plane_surf(plane_state, 0));
1408 }
1409
1410 static void icl_plane_update_sel_fetch_noarm(struct intel_dsb *dsb,
1411                                              struct intel_plane *plane,
1412                                              const struct intel_crtc_state *crtc_state,
1413                                              const struct intel_plane_state *plane_state,
1414                                              int color_plane)
1415 {
1416         struct intel_display *display = to_intel_display(plane->base.dev);
1417         enum pipe pipe = plane->pipe;
1418         const struct drm_rect *clip;
1419         u32 val;
1420         int x, y;
1421
1422         if (!crtc_state->enable_psr2_sel_fetch)
1423                 return;
1424
1425         clip = &plane_state->psr2_sel_fetch_area;
1426
1427         if (crtc_state->enable_psr2_su_region_et)
1428                 y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1);
1429         else
1430                 y = (clip->y1 + plane_state->uapi.dst.y1);
1431         val = y << 16;
1432         val |= plane_state->uapi.dst.x1;
1433         intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_POS(pipe, plane->id), val);
1434
1435         x = plane_state->view.color_plane[color_plane].x;
1436
1437         /*
1438          * From Bspec: UV surface Start Y Position = half of Y plane Y
1439          * start position.
1440          */
1441         if (!color_plane)
1442                 y = plane_state->view.color_plane[color_plane].y + clip->y1;
1443         else
1444                 y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2;
1445
1446         val = y << 16 | x;
1447
1448         intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_OFFSET(pipe, plane->id), val);
1449
1450         /* Sizes are 0 based */
1451         val = (drm_rect_height(clip) - 1) << 16;
1452         val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1;
1453         intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val);
1454 }
1455
1456 static void
1457 icl_plane_update_noarm(struct intel_dsb *dsb,
1458                        struct intel_plane *plane,
1459                        const struct intel_crtc_state *crtc_state,
1460                        const struct intel_plane_state *plane_state)
1461 {
1462         struct intel_display *display = to_intel_display(plane->base.dev);
1463         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1464         enum plane_id plane_id = plane->id;
1465         enum pipe pipe = plane->pipe;
1466         int color_plane = icl_plane_color_plane(plane_state);
1467         u32 stride = skl_plane_stride(plane_state, color_plane);
1468         const struct drm_framebuffer *fb = plane_state->hw.fb;
1469         int crtc_x = plane_state->uapi.dst.x1;
1470         int crtc_y = plane_state->uapi.dst.y1;
1471         int x = plane_state->view.color_plane[color_plane].x;
1472         int y = plane_state->view.color_plane[color_plane].y;
1473         int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1474         int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1475         u32 plane_color_ctl;
1476
1477         plane_color_ctl = plane_state->color_ctl |
1478                 glk_plane_color_ctl_crtc(crtc_state);
1479
1480         /* The scaler will handle the output position */
1481         if (plane_state->scaler_id >= 0) {
1482                 crtc_x = 0;
1483                 crtc_y = 0;
1484         }
1485
1486         intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id),
1487                            PLANE_STRIDE_(stride));
1488         intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id),
1489                            PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1490         intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id),
1491                            PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1492
1493         intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id),
1494                            skl_plane_keyval(plane_state));
1495         intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id),
1496                            skl_plane_keymsk(plane_state));
1497         intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id),
1498                            skl_plane_keymax(plane_state));
1499
1500         intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id),
1501                            PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1502
1503         if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
1504                 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 0),
1505                                    lower_32_bits(plane_state->ccval));
1506                 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 1),
1507                                    upper_32_bits(plane_state->ccval));
1508         }
1509
1510         /* FLAT CCS doesn't need to program AUX_DIST */
1511         if (!HAS_FLAT_CCS(dev_priv) && DISPLAY_VER(dev_priv) < 20)
1512                 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id),
1513                                    skl_plane_aux_dist(plane_state, color_plane));
1514
1515         if (icl_is_hdr_plane(dev_priv, plane_id))
1516                 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id),
1517                                    plane_state->cus_ctl);
1518
1519         intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id),
1520                            plane_color_ctl);
1521
1522         if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1523                 icl_program_input_csc(dsb, plane, plane_state);
1524
1525         skl_write_plane_wm(dsb, plane, crtc_state);
1526
1527         /*
1528          * FIXME: pxp session invalidation can hit any time even at time of commit
1529          * or after the commit, display content will be garbage.
1530          */
1531         if (plane_state->force_black)
1532                 icl_plane_csc_load_black(dsb, plane, crtc_state);
1533
1534         icl_plane_update_sel_fetch_noarm(dsb, plane, crtc_state, plane_state, color_plane);
1535 }
1536
1537 static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb,
1538                                            struct intel_plane *plane,
1539                                            const struct intel_crtc_state *crtc_state,
1540                                            const struct intel_plane_state *plane_state)
1541 {
1542         struct intel_display *display = to_intel_display(plane->base.dev);
1543         enum pipe pipe = plane->pipe;
1544
1545         if (!crtc_state->enable_psr2_sel_fetch)
1546                 return;
1547
1548         if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
1549                 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id),
1550                                    SEL_FETCH_PLANE_CTL_ENABLE);
1551         else
1552                 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state);
1553 }
1554
1555 static void
1556 icl_plane_update_arm(struct intel_dsb *dsb,
1557                      struct intel_plane *plane,
1558                      const struct intel_crtc_state *crtc_state,
1559                      const struct intel_plane_state *plane_state)
1560 {
1561         struct intel_display *display = to_intel_display(plane->base.dev);
1562         enum plane_id plane_id = plane->id;
1563         enum pipe pipe = plane->pipe;
1564         int color_plane = icl_plane_color_plane(plane_state);
1565         u32 plane_ctl;
1566
1567         plane_ctl = plane_state->ctl |
1568                 skl_plane_ctl_crtc(crtc_state);
1569
1570         /*
1571          * Enable the scaler before the plane so that we don't
1572          * get a catastrophic underrun even if the two operations
1573          * end up happening in two different frames.
1574          *
1575          * TODO: split into noarm+arm pair
1576          */
1577         if (plane_state->scaler_id >= 0)
1578                 skl_program_plane_scaler(plane, crtc_state, plane_state);
1579
1580         icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
1581
1582         /*
1583          * The control register self-arms if the plane was previously
1584          * disabled. Try to make the plane enable atomic by writing
1585          * the control register just before the surface register.
1586          */
1587         intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1588                            plane_ctl);
1589         intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1590                            skl_plane_surf(plane_state, color_plane));
1591 }
1592
1593 static void
1594 skl_plane_async_flip(struct intel_dsb *dsb,
1595                      struct intel_plane *plane,
1596                      const struct intel_crtc_state *crtc_state,
1597                      const struct intel_plane_state *plane_state,
1598                      bool async_flip)
1599 {
1600         struct intel_display *display = to_intel_display(plane->base.dev);
1601         enum plane_id plane_id = plane->id;
1602         enum pipe pipe = plane->pipe;
1603         u32 plane_ctl = plane_state->ctl, plane_surf;
1604
1605         plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1606         plane_surf = skl_plane_surf(plane_state, 0);
1607
1608         if (async_flip) {
1609                 if (DISPLAY_VER(display) >= 30)
1610                         plane_surf |= PLANE_SURF_ASYNC_UPDATE;
1611                 else
1612                         plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1613         }
1614
1615         intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1616                            plane_ctl);
1617         intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1618                            plane_surf);
1619 }
1620
1621 static bool intel_format_is_p01x(u32 format)
1622 {
1623         switch (format) {
1624         case DRM_FORMAT_P010:
1625         case DRM_FORMAT_P012:
1626         case DRM_FORMAT_P016:
1627                 return true;
1628         default:
1629                 return false;
1630         }
1631 }
1632
1633 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1634                               const struct intel_plane_state *plane_state)
1635 {
1636         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1637         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1638         const struct drm_framebuffer *fb = plane_state->hw.fb;
1639         unsigned int rotation = plane_state->hw.rotation;
1640
1641         if (!fb)
1642                 return 0;
1643
1644         if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1645             intel_fb_is_ccs_modifier(fb->modifier)) {
1646                 drm_dbg_kms(&dev_priv->drm,
1647                             "RC support only with 0/180 degree rotation (%x)\n",
1648                             rotation);
1649                 return -EINVAL;
1650         }
1651
1652         if (rotation & DRM_MODE_REFLECT_X &&
1653             fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1654                 drm_dbg_kms(&dev_priv->drm,
1655                             "horizontal flip is not supported with linear surface formats\n");
1656                 return -EINVAL;
1657         }
1658
1659         /*
1660          * Display20 onward tile4 hflip is not supported
1661          */
1662         if (rotation & DRM_MODE_REFLECT_X &&
1663             intel_fb_is_tile4_modifier(fb->modifier) &&
1664             DISPLAY_VER(dev_priv) >= 20) {
1665                 drm_dbg_kms(&dev_priv->drm,
1666                             "horizontal flip is not supported with tile4 surface formats\n");
1667                 return -EINVAL;
1668         }
1669
1670         if (drm_rotation_90_or_270(rotation)) {
1671                 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
1672                         drm_dbg_kms(&dev_priv->drm,
1673                                     "Y/Yf tiling required for 90/270!\n");
1674                         return -EINVAL;
1675                 }
1676
1677                 /*
1678                  * 90/270 is not allowed with RGB64 16:16:16:16 and
1679                  * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1680                  */
1681                 switch (fb->format->format) {
1682                 case DRM_FORMAT_RGB565:
1683                         if (DISPLAY_VER(dev_priv) >= 11)
1684                                 break;
1685                         fallthrough;
1686                 case DRM_FORMAT_C8:
1687                 case DRM_FORMAT_XRGB16161616F:
1688                 case DRM_FORMAT_XBGR16161616F:
1689                 case DRM_FORMAT_ARGB16161616F:
1690                 case DRM_FORMAT_ABGR16161616F:
1691                 case DRM_FORMAT_Y210:
1692                 case DRM_FORMAT_Y212:
1693                 case DRM_FORMAT_Y216:
1694                 case DRM_FORMAT_XVYU12_16161616:
1695                 case DRM_FORMAT_XVYU16161616:
1696                         drm_dbg_kms(&dev_priv->drm,
1697                                     "Unsupported pixel format %p4cc for 90/270!\n",
1698                                     &fb->format->format);
1699                         return -EINVAL;
1700                 default:
1701                         break;
1702                 }
1703         }
1704
1705         /* Y-tiling is not supported in IF-ID Interlace mode */
1706         if (crtc_state->hw.enable &&
1707             crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1708             fb->modifier != DRM_FORMAT_MOD_LINEAR &&
1709             fb->modifier != I915_FORMAT_MOD_X_TILED) {
1710                 drm_dbg_kms(&dev_priv->drm,
1711                             "Y/Yf tiling not supported in IF-ID mode\n");
1712                 return -EINVAL;
1713         }
1714
1715         /* Wa_1606054188:tgl,adl-s */
1716         if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1717             plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1718             intel_format_is_p01x(fb->format->format)) {
1719                 drm_dbg_kms(&dev_priv->drm,
1720                             "Source color keying not supported with P01x formats\n");
1721                 return -EINVAL;
1722         }
1723
1724         return 0;
1725 }
1726
1727 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1728                                            const struct intel_plane_state *plane_state)
1729 {
1730         struct drm_i915_private *dev_priv =
1731                 to_i915(plane_state->uapi.plane->dev);
1732         int crtc_x = plane_state->uapi.dst.x1;
1733         int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1734         int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
1735
1736         /*
1737          * Display WA #1175: glk
1738          * Planes other than the cursor may cause FIFO underflow and display
1739          * corruption if starting less than 4 pixels from the right edge of
1740          * the screen.
1741          * Besides the above WA fix the similar problem, where planes other
1742          * than the cursor ending less than 4 pixels from the left edge of the
1743          * screen may cause FIFO underflow and display corruption.
1744          */
1745         if (DISPLAY_VER(dev_priv) == 10 &&
1746             (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1747                 drm_dbg_kms(&dev_priv->drm,
1748                             "requested plane X %s position %d invalid (valid range %d-%d)\n",
1749                             crtc_x + crtc_w < 4 ? "end" : "start",
1750                             crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1751                             4, pipe_src_w - 4);
1752                 return -ERANGE;
1753         }
1754
1755         return 0;
1756 }
1757
1758 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1759 {
1760         struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1761         const struct drm_framebuffer *fb = plane_state->hw.fb;
1762         unsigned int rotation = plane_state->hw.rotation;
1763         int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1764
1765         /* Display WA #1106 */
1766         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1767             src_w & 3 &&
1768             (rotation == DRM_MODE_ROTATE_270 ||
1769              rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1770                 drm_dbg_kms(&i915->drm, "src width must be multiple of 4 for rotated planar YUV\n");
1771                 return -EINVAL;
1772         }
1773
1774         return 0;
1775 }
1776
1777 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1778                                const struct drm_framebuffer *fb)
1779 {
1780         /*
1781          * We don't yet know the final source width nor
1782          * whether we can use the HQ scaler mode. Assume
1783          * the best case.
1784          * FIXME need to properly check this later.
1785          */
1786         if (DISPLAY_VER(dev_priv) >= 10 ||
1787             !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1788                 return 0x30000 - 1;
1789         else
1790                 return 0x20000 - 1;
1791 }
1792
1793 static int intel_plane_min_width(struct intel_plane *plane,
1794                                  const struct drm_framebuffer *fb,
1795                                  int color_plane,
1796                                  unsigned int rotation)
1797 {
1798         if (plane->min_width)
1799                 return plane->min_width(fb, color_plane, rotation);
1800         else
1801                 return 1;
1802 }
1803
1804 static int intel_plane_max_width(struct intel_plane *plane,
1805                                  const struct drm_framebuffer *fb,
1806                                  int color_plane,
1807                                  unsigned int rotation)
1808 {
1809         if (plane->max_width)
1810                 return plane->max_width(fb, color_plane, rotation);
1811         else
1812                 return INT_MAX;
1813 }
1814
1815 static int intel_plane_max_height(struct intel_plane *plane,
1816                                   const struct drm_framebuffer *fb,
1817                                   int color_plane,
1818                                   unsigned int rotation)
1819 {
1820         if (plane->max_height)
1821                 return plane->max_height(fb, color_plane, rotation);
1822         else
1823                 return INT_MAX;
1824 }
1825
1826 static bool
1827 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1828                                int main_x, int main_y, u32 main_offset,
1829                                int ccs_plane)
1830 {
1831         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1832         const struct drm_framebuffer *fb = plane_state->hw.fb;
1833         int aux_x = plane_state->view.color_plane[ccs_plane].x;
1834         int aux_y = plane_state->view.color_plane[ccs_plane].y;
1835         u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1836         unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane);
1837         int hsub;
1838         int vsub;
1839
1840         intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1841         while (aux_offset >= main_offset && aux_y <= main_y) {
1842                 int x, y;
1843
1844                 if (aux_x == main_x && aux_y == main_y)
1845                         break;
1846
1847                 if (aux_offset == 0)
1848                         break;
1849
1850                 x = aux_x / hsub;
1851                 y = aux_y / vsub;
1852                 aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1853                                                                plane_state,
1854                                                                ccs_plane,
1855                                                                aux_offset,
1856                                                                aux_offset - alignment);
1857                 aux_x = x * hsub + aux_x % hsub;
1858                 aux_y = y * vsub + aux_y % vsub;
1859         }
1860
1861         if (aux_x != main_x || aux_y != main_y)
1862                 return false;
1863
1864         plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1865         plane_state->view.color_plane[ccs_plane].x = aux_x;
1866         plane_state->view.color_plane[ccs_plane].y = aux_y;
1867
1868         return true;
1869 }
1870
1871
1872 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1873                                  int *x, int *y, u32 *offset)
1874 {
1875         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1876         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1877         const struct drm_framebuffer *fb = plane_state->hw.fb;
1878         int aux_plane = skl_main_to_aux_plane(fb, 0);
1879         u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1880         unsigned int alignment = plane->min_alignment(plane, fb, 0);
1881         int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1882
1883         intel_add_fb_offsets(x, y, plane_state, 0);
1884         *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1885         if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1886                 return -EINVAL;
1887
1888         /*
1889          * AUX surface offset is specified as the distance from the
1890          * main surface offset, and it must be non-negative. Make
1891          * sure that is what we will get.
1892          */
1893         if (aux_plane && *offset > aux_offset)
1894                 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1895                                                             *offset,
1896                                                             aux_offset & ~(alignment - 1));
1897
1898         /*
1899          * When using an X-tiled surface, the plane blows up
1900          * if the x offset + width exceed the stride.
1901          *
1902          * TODO: linear and Y-tiled seem fine, Yf untested,
1903          */
1904         if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1905                 int cpp = fb->format->cpp[0];
1906
1907                 while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
1908                         if (*offset == 0) {
1909                                 drm_dbg_kms(&dev_priv->drm,
1910                                             "Unable to find suitable display surface offset due to X-tiling\n");
1911                                 return -EINVAL;
1912                         }
1913
1914                         *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1915                                                                     *offset,
1916                                                                     *offset - alignment);
1917                 }
1918         }
1919
1920         return 0;
1921 }
1922
1923 static int skl_check_main_surface(struct intel_plane_state *plane_state)
1924 {
1925         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1926         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1927         const struct drm_framebuffer *fb = plane_state->hw.fb;
1928         unsigned int rotation = plane_state->hw.rotation;
1929         int x = plane_state->uapi.src.x1 >> 16;
1930         int y = plane_state->uapi.src.y1 >> 16;
1931         int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1932         int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1933         int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1934         int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1935         int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1936         unsigned int alignment = plane->min_alignment(plane, fb, 0);
1937         int aux_plane = skl_main_to_aux_plane(fb, 0);
1938         u32 offset;
1939         int ret;
1940
1941         if (w > max_width || w < min_width || h > max_height || h < 1) {
1942                 drm_dbg_kms(&dev_priv->drm,
1943                             "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1944                             w, h, min_width, max_width, max_height);
1945                 return -EINVAL;
1946         }
1947
1948         ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1949         if (ret)
1950                 return ret;
1951
1952         /*
1953          * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1954          * they match with the main surface x/y offsets. On DG2
1955          * there's no aux plane on fb so skip this checking.
1956          */
1957         if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) {
1958                 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1959                                                        offset, aux_plane)) {
1960                         if (offset == 0)
1961                                 break;
1962
1963                         offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1964                                                                    offset, offset - alignment);
1965                 }
1966
1967                 if (x != plane_state->view.color_plane[aux_plane].x ||
1968                     y != plane_state->view.color_plane[aux_plane].y) {
1969                         drm_dbg_kms(&dev_priv->drm,
1970                                     "Unable to find suitable display surface offset due to CCS\n");
1971                         return -EINVAL;
1972                 }
1973         }
1974
1975         if (DISPLAY_VER(dev_priv) >= 13)
1976                 drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
1977         else
1978                 drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1979
1980         plane_state->view.color_plane[0].offset = offset;
1981         plane_state->view.color_plane[0].x = x;
1982         plane_state->view.color_plane[0].y = y;
1983
1984         /*
1985          * Put the final coordinates back so that the src
1986          * coordinate checks will see the right values.
1987          */
1988         drm_rect_translate_to(&plane_state->uapi.src,
1989                               x << 16, y << 16);
1990
1991         return 0;
1992 }
1993
1994 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1995 {
1996         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1997         struct drm_i915_private *i915 = to_i915(plane->base.dev);
1998         const struct drm_framebuffer *fb = plane_state->hw.fb;
1999         unsigned int rotation = plane_state->hw.rotation;
2000         int uv_plane = 1;
2001         int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
2002                         skl_main_to_aux_plane(fb, uv_plane) : 0;
2003         int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
2004         int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
2005         int x = plane_state->uapi.src.x1 >> 17;
2006         int y = plane_state->uapi.src.y1 >> 17;
2007         int w = drm_rect_width(&plane_state->uapi.src) >> 17;
2008         int h = drm_rect_height(&plane_state->uapi.src) >> 17;
2009         u32 offset;
2010
2011         /* FIXME not quite sure how/if these apply to the chroma plane */
2012         if (w > max_width || h > max_height) {
2013                 drm_dbg_kms(&i915->drm,
2014                             "CbCr source size %dx%d too big (limit %dx%d)\n",
2015                             w, h, max_width, max_height);
2016                 return -EINVAL;
2017         }
2018
2019         intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
2020         offset = intel_plane_compute_aligned_offset(&x, &y,
2021                                                     plane_state, uv_plane);
2022
2023         if (ccs_plane) {
2024                 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
2025                 unsigned int alignment = plane->min_alignment(plane, fb, uv_plane);
2026
2027                 if (offset > aux_offset)
2028                         offset = intel_plane_adjust_aligned_offset(&x, &y,
2029                                                                    plane_state,
2030                                                                    uv_plane,
2031                                                                    offset,
2032                                                                    aux_offset & ~(alignment - 1));
2033
2034                 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
2035                                                        offset, ccs_plane)) {
2036                         if (offset == 0)
2037                                 break;
2038
2039                         offset = intel_plane_adjust_aligned_offset(&x, &y,
2040                                                                    plane_state,
2041                                                                    uv_plane,
2042                                                                    offset, offset - alignment);
2043                 }
2044
2045                 if (x != plane_state->view.color_plane[ccs_plane].x ||
2046                     y != plane_state->view.color_plane[ccs_plane].y) {
2047                         drm_dbg_kms(&i915->drm,
2048                                     "Unable to find suitable display surface offset due to CCS\n");
2049                         return -EINVAL;
2050                 }
2051         }
2052
2053         if (DISPLAY_VER(i915) >= 13)
2054                 drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
2055         else
2056                 drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
2057
2058         plane_state->view.color_plane[uv_plane].offset = offset;
2059         plane_state->view.color_plane[uv_plane].x = x;
2060         plane_state->view.color_plane[uv_plane].y = y;
2061
2062         return 0;
2063 }
2064
2065 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
2066 {
2067         const struct drm_framebuffer *fb = plane_state->hw.fb;
2068         int src_x = plane_state->uapi.src.x1 >> 16;
2069         int src_y = plane_state->uapi.src.y1 >> 16;
2070         u32 offset;
2071         int ccs_plane;
2072
2073         for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
2074                 int main_hsub, main_vsub;
2075                 int hsub, vsub;
2076                 int x, y;
2077
2078                 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane))
2079                         continue;
2080
2081                 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
2082                                                skl_ccs_to_main_plane(fb, ccs_plane));
2083                 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
2084
2085                 hsub *= main_hsub;
2086                 vsub *= main_vsub;
2087                 x = src_x / hsub;
2088                 y = src_y / vsub;
2089
2090                 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
2091
2092                 offset = intel_plane_compute_aligned_offset(&x, &y,
2093                                                             plane_state,
2094                                                             ccs_plane);
2095
2096                 plane_state->view.color_plane[ccs_plane].offset = offset;
2097                 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
2098                 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
2099         }
2100
2101         return 0;
2102 }
2103
2104 static int skl_check_plane_surface(struct intel_plane_state *plane_state)
2105 {
2106         const struct drm_framebuffer *fb = plane_state->hw.fb;
2107         int ret;
2108
2109         ret = intel_plane_compute_gtt(plane_state);
2110         if (ret)
2111                 return ret;
2112
2113         if (!plane_state->uapi.visible)
2114                 return 0;
2115
2116         /*
2117          * Handle the AUX surface first since the main surface setup depends on
2118          * it.
2119          */
2120         if (intel_fb_is_ccs_modifier(fb->modifier)) {
2121                 ret = skl_check_ccs_aux_surface(plane_state);
2122                 if (ret)
2123                         return ret;
2124         }
2125
2126         if (intel_format_info_is_yuv_semiplanar(fb->format,
2127                                                 fb->modifier)) {
2128                 ret = skl_check_nv12_aux_surface(plane_state);
2129                 if (ret)
2130                         return ret;
2131         }
2132
2133         ret = skl_check_main_surface(plane_state);
2134         if (ret)
2135                 return ret;
2136
2137         return 0;
2138 }
2139
2140 static bool skl_fb_scalable(const struct drm_framebuffer *fb)
2141 {
2142         if (!fb)
2143                 return false;
2144
2145         switch (fb->format->format) {
2146         case DRM_FORMAT_C8:
2147                 return false;
2148         case DRM_FORMAT_XRGB16161616F:
2149         case DRM_FORMAT_ARGB16161616F:
2150         case DRM_FORMAT_XBGR16161616F:
2151         case DRM_FORMAT_ABGR16161616F:
2152                 return DISPLAY_VER(to_i915(fb->dev)) >= 11;
2153         default:
2154                 return true;
2155         }
2156 }
2157
2158 static void check_protection(struct intel_plane_state *plane_state)
2159 {
2160         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2161         struct drm_i915_private *i915 = to_i915(plane->base.dev);
2162         const struct drm_framebuffer *fb = plane_state->hw.fb;
2163         struct drm_gem_object *obj = intel_fb_bo(fb);
2164
2165         if (DISPLAY_VER(i915) < 11)
2166                 return;
2167
2168         plane_state->decrypt = intel_pxp_key_check(i915->pxp, obj, false) == 0;
2169         plane_state->force_black = intel_bo_is_protected(obj) &&
2170                 !plane_state->decrypt;
2171 }
2172
2173 static int skl_plane_check(struct intel_crtc_state *crtc_state,
2174                            struct intel_plane_state *plane_state)
2175 {
2176         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2177         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2178         const struct drm_framebuffer *fb = plane_state->hw.fb;
2179         int min_scale = DRM_PLANE_NO_SCALING;
2180         int max_scale = DRM_PLANE_NO_SCALING;
2181         int ret;
2182
2183         ret = skl_plane_check_fb(crtc_state, plane_state);
2184         if (ret)
2185                 return ret;
2186
2187         /* use scaler when colorkey is not required */
2188         if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
2189                 min_scale = 1;
2190                 max_scale = skl_plane_max_scale(dev_priv, fb);
2191         }
2192
2193         ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
2194                                                 min_scale, max_scale, true);
2195         if (ret)
2196                 return ret;
2197
2198         ret = skl_check_plane_surface(plane_state);
2199         if (ret)
2200                 return ret;
2201
2202         if (!plane_state->uapi.visible)
2203                 return 0;
2204
2205         ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2206         if (ret)
2207                 return ret;
2208
2209         ret = intel_plane_check_src_coordinates(plane_state);
2210         if (ret)
2211                 return ret;
2212
2213         ret = skl_plane_check_nv12_rotation(plane_state);
2214         if (ret)
2215                 return ret;
2216
2217         check_protection(plane_state);
2218
2219         /* HW only has 8 bits pixel precision, disable plane if invisible */
2220         if (!(plane_state->hw.alpha >> 8))
2221                 plane_state->uapi.visible = false;
2222
2223         plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
2224
2225         if (DISPLAY_VER(dev_priv) >= 10)
2226                 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
2227                                                              plane_state);
2228
2229         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2230             icl_is_hdr_plane(dev_priv, plane->id))
2231                 /* Enable and use MPEG-2 chroma siting */
2232                 plane_state->cus_ctl = PLANE_CUS_ENABLE |
2233                         PLANE_CUS_HPHASE_0 |
2234                         PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2235         else
2236                 plane_state->cus_ctl = 0;
2237
2238         return 0;
2239 }
2240
2241 static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
2242 {
2243         return pipe - PIPE_A + INTEL_FBC_A;
2244 }
2245
2246 static bool skl_plane_has_fbc(struct drm_i915_private *i915,
2247                               enum intel_fbc_id fbc_id, enum plane_id plane_id)
2248 {
2249         if ((DISPLAY_RUNTIME_INFO(i915)->fbc_mask & BIT(fbc_id)) == 0)
2250                 return false;
2251
2252         if (DISPLAY_VER(i915) >= 20)
2253                 return icl_is_hdr_plane(i915, plane_id);
2254         else
2255                 return plane_id == PLANE_1;
2256 }
2257
2258 static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv,
2259                                        enum pipe pipe, enum plane_id plane_id)
2260 {
2261         enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
2262
2263         if (skl_plane_has_fbc(dev_priv, fbc_id, plane_id))
2264                 return dev_priv->display.fbc[fbc_id];
2265         else
2266                 return NULL;
2267 }
2268
2269 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2270                                  enum pipe pipe, enum plane_id plane_id)
2271 {
2272         /* Display WA #0870: skl, bxt */
2273         if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2274                 return false;
2275
2276         if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
2277                 return false;
2278
2279         if (plane_id != PLANE_1 && plane_id != PLANE_2)
2280                 return false;
2281
2282         return true;
2283 }
2284
2285 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2286                                         enum pipe pipe, enum plane_id plane_id,
2287                                         int *num_formats)
2288 {
2289         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2290                 *num_formats = ARRAY_SIZE(skl_planar_formats);
2291                 return skl_planar_formats;
2292         } else {
2293                 *num_formats = ARRAY_SIZE(skl_plane_formats);
2294                 return skl_plane_formats;
2295         }
2296 }
2297
2298 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2299                                         enum pipe pipe, enum plane_id plane_id,
2300                                         int *num_formats)
2301 {
2302         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2303                 *num_formats = ARRAY_SIZE(glk_planar_formats);
2304                 return glk_planar_formats;
2305         } else {
2306                 *num_formats = ARRAY_SIZE(skl_plane_formats);
2307                 return skl_plane_formats;
2308         }
2309 }
2310
2311 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2312                                         enum pipe pipe, enum plane_id plane_id,
2313                                         int *num_formats)
2314 {
2315         if (icl_is_hdr_plane(dev_priv, plane_id)) {
2316                 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2317                 return icl_hdr_plane_formats;
2318         } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
2319                 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2320                 return icl_sdr_y_plane_formats;
2321         } else {
2322                 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2323                 return icl_sdr_uv_plane_formats;
2324         }
2325 }
2326
2327 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2328                                            u32 format, u64 modifier)
2329 {
2330         struct intel_plane *plane = to_intel_plane(_plane);
2331
2332         if (!intel_fb_plane_supports_modifier(plane, modifier))
2333                 return false;
2334
2335         switch (format) {
2336         case DRM_FORMAT_XRGB8888:
2337         case DRM_FORMAT_XBGR8888:
2338         case DRM_FORMAT_ARGB8888:
2339         case DRM_FORMAT_ABGR8888:
2340                 if (intel_fb_is_ccs_modifier(modifier))
2341                         return true;
2342                 fallthrough;
2343         case DRM_FORMAT_RGB565:
2344         case DRM_FORMAT_XRGB2101010:
2345         case DRM_FORMAT_XBGR2101010:
2346         case DRM_FORMAT_ARGB2101010:
2347         case DRM_FORMAT_ABGR2101010:
2348         case DRM_FORMAT_YUYV:
2349         case DRM_FORMAT_YVYU:
2350         case DRM_FORMAT_UYVY:
2351         case DRM_FORMAT_VYUY:
2352         case DRM_FORMAT_NV12:
2353         case DRM_FORMAT_XYUV8888:
2354         case DRM_FORMAT_P010:
2355         case DRM_FORMAT_P012:
2356         case DRM_FORMAT_P016:
2357         case DRM_FORMAT_XVYU2101010:
2358                 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2359                         return true;
2360                 fallthrough;
2361         case DRM_FORMAT_C8:
2362         case DRM_FORMAT_XBGR16161616F:
2363         case DRM_FORMAT_ABGR16161616F:
2364         case DRM_FORMAT_XRGB16161616F:
2365         case DRM_FORMAT_ARGB16161616F:
2366         case DRM_FORMAT_Y210:
2367         case DRM_FORMAT_Y212:
2368         case DRM_FORMAT_Y216:
2369         case DRM_FORMAT_XVYU12_16161616:
2370         case DRM_FORMAT_XVYU16161616:
2371                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2372                     modifier == I915_FORMAT_MOD_X_TILED ||
2373                     modifier == I915_FORMAT_MOD_Y_TILED)
2374                         return true;
2375                 fallthrough;
2376         default:
2377                 return false;
2378         }
2379 }
2380
2381 static bool icl_plane_format_mod_supported(struct drm_plane *_plane,
2382                                            u32 format, u64 modifier)
2383 {
2384         struct intel_plane *plane = to_intel_plane(_plane);
2385
2386         if (!intel_fb_plane_supports_modifier(plane, modifier))
2387                 return false;
2388
2389         switch (format) {
2390         case DRM_FORMAT_XRGB8888:
2391         case DRM_FORMAT_XBGR8888:
2392         case DRM_FORMAT_ARGB8888:
2393         case DRM_FORMAT_ABGR8888:
2394         case DRM_FORMAT_XRGB2101010:
2395         case DRM_FORMAT_XBGR2101010:
2396         case DRM_FORMAT_ARGB2101010:
2397         case DRM_FORMAT_ABGR2101010:
2398                 if (intel_fb_is_ccs_modifier(modifier))
2399                         return true;
2400                 fallthrough;
2401         case DRM_FORMAT_RGB565:
2402         case DRM_FORMAT_YUYV:
2403         case DRM_FORMAT_YVYU:
2404         case DRM_FORMAT_UYVY:
2405         case DRM_FORMAT_VYUY:
2406         case DRM_FORMAT_NV12:
2407         case DRM_FORMAT_XYUV8888:
2408         case DRM_FORMAT_P010:
2409         case DRM_FORMAT_P012:
2410         case DRM_FORMAT_P016:
2411         case DRM_FORMAT_XVYU2101010:
2412                 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2413                         return true;
2414                 fallthrough;
2415         case DRM_FORMAT_C8:
2416         case DRM_FORMAT_XBGR16161616F:
2417         case DRM_FORMAT_ABGR16161616F:
2418         case DRM_FORMAT_XRGB16161616F:
2419         case DRM_FORMAT_ARGB16161616F:
2420         case DRM_FORMAT_Y210:
2421         case DRM_FORMAT_Y212:
2422         case DRM_FORMAT_Y216:
2423         case DRM_FORMAT_XVYU12_16161616:
2424         case DRM_FORMAT_XVYU16161616:
2425                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2426                     modifier == I915_FORMAT_MOD_X_TILED ||
2427                     modifier == I915_FORMAT_MOD_Y_TILED)
2428                         return true;
2429                 fallthrough;
2430         default:
2431                 return false;
2432         }
2433 }
2434
2435 static bool tgl_plane_format_mod_supported(struct drm_plane *_plane,
2436                                            u32 format, u64 modifier)
2437 {
2438         struct intel_plane *plane = to_intel_plane(_plane);
2439
2440         if (!intel_fb_plane_supports_modifier(plane, modifier))
2441                 return false;
2442
2443         switch (format) {
2444         case DRM_FORMAT_XRGB8888:
2445         case DRM_FORMAT_XBGR8888:
2446         case DRM_FORMAT_ARGB8888:
2447         case DRM_FORMAT_ABGR8888:
2448         case DRM_FORMAT_XRGB2101010:
2449         case DRM_FORMAT_XBGR2101010:
2450         case DRM_FORMAT_ARGB2101010:
2451         case DRM_FORMAT_ABGR2101010:
2452         case DRM_FORMAT_XBGR16161616F:
2453         case DRM_FORMAT_ABGR16161616F:
2454         case DRM_FORMAT_XRGB16161616F:
2455         case DRM_FORMAT_ARGB16161616F:
2456                 if (intel_fb_is_ccs_modifier(modifier))
2457                         return true;
2458                 fallthrough;
2459         case DRM_FORMAT_YUYV:
2460         case DRM_FORMAT_YVYU:
2461         case DRM_FORMAT_UYVY:
2462         case DRM_FORMAT_VYUY:
2463         case DRM_FORMAT_NV12:
2464         case DRM_FORMAT_XYUV8888:
2465         case DRM_FORMAT_P010:
2466         case DRM_FORMAT_P012:
2467         case DRM_FORMAT_P016:
2468                 if (intel_fb_is_mc_ccs_modifier(modifier))
2469                         return true;
2470                 fallthrough;
2471         case DRM_FORMAT_RGB565:
2472         case DRM_FORMAT_XVYU2101010:
2473         case DRM_FORMAT_C8:
2474         case DRM_FORMAT_Y210:
2475         case DRM_FORMAT_Y212:
2476         case DRM_FORMAT_Y216:
2477         case DRM_FORMAT_XVYU12_16161616:
2478         case DRM_FORMAT_XVYU16161616:
2479                 if (!intel_fb_is_ccs_modifier(modifier))
2480                         return true;
2481                 fallthrough;
2482         default:
2483                 return false;
2484         }
2485 }
2486
2487 static const struct drm_plane_funcs skl_plane_funcs = {
2488         .update_plane = drm_atomic_helper_update_plane,
2489         .disable_plane = drm_atomic_helper_disable_plane,
2490         .destroy = intel_plane_destroy,
2491         .atomic_duplicate_state = intel_plane_duplicate_state,
2492         .atomic_destroy_state = intel_plane_destroy_state,
2493         .format_mod_supported = skl_plane_format_mod_supported,
2494 };
2495
2496 static const struct drm_plane_funcs icl_plane_funcs = {
2497         .update_plane = drm_atomic_helper_update_plane,
2498         .disable_plane = drm_atomic_helper_disable_plane,
2499         .destroy = intel_plane_destroy,
2500         .atomic_duplicate_state = intel_plane_duplicate_state,
2501         .atomic_destroy_state = intel_plane_destroy_state,
2502         .format_mod_supported = icl_plane_format_mod_supported,
2503 };
2504
2505 static const struct drm_plane_funcs tgl_plane_funcs = {
2506         .update_plane = drm_atomic_helper_update_plane,
2507         .disable_plane = drm_atomic_helper_disable_plane,
2508         .destroy = intel_plane_destroy,
2509         .atomic_duplicate_state = intel_plane_duplicate_state,
2510         .atomic_destroy_state = intel_plane_destroy_state,
2511         .format_mod_supported = tgl_plane_format_mod_supported,
2512 };
2513
2514 static void
2515 skl_plane_enable_flip_done(struct intel_plane *plane)
2516 {
2517         struct drm_i915_private *i915 = to_i915(plane->base.dev);
2518         enum pipe pipe = plane->pipe;
2519
2520         spin_lock_irq(&i915->irq_lock);
2521         bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2522         spin_unlock_irq(&i915->irq_lock);
2523 }
2524
2525 static void
2526 skl_plane_disable_flip_done(struct intel_plane *plane)
2527 {
2528         struct drm_i915_private *i915 = to_i915(plane->base.dev);
2529         enum pipe pipe = plane->pipe;
2530
2531         spin_lock_irq(&i915->irq_lock);
2532         bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2533         spin_unlock_irq(&i915->irq_lock);
2534 }
2535
2536 static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915,
2537                                  enum pipe pipe, enum plane_id plane_id)
2538 {
2539         /* Wa_22011186057 */
2540         if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2541                 return false;
2542
2543         if (DISPLAY_VER(i915) >= 11)
2544                 return true;
2545
2546         if (IS_GEMINILAKE(i915))
2547                 return pipe != PIPE_C;
2548
2549         return pipe != PIPE_C &&
2550                 (plane_id == PLANE_1 || plane_id == PLANE_2);
2551 }
2552
2553 static bool tgl_plane_has_mc_ccs(struct drm_i915_private *i915,
2554                                  enum plane_id plane_id)
2555 {
2556         if (DISPLAY_VER(i915) < 12)
2557                 return false;
2558
2559         /* Wa_14010477008 */
2560         if (IS_DG1(i915) || IS_ROCKETLAKE(i915) ||
2561                 (IS_TIGERLAKE(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_D0)))
2562                 return false;
2563
2564         /* Wa_22011186057 */
2565         if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2566                 return false;
2567
2568         return plane_id < PLANE_6;
2569 }
2570
2571 static u8 skl_get_plane_caps(struct drm_i915_private *i915,
2572                              enum pipe pipe, enum plane_id plane_id)
2573 {
2574         struct intel_display *display = &i915->display;
2575         u8 caps = INTEL_PLANE_CAP_TILING_X;
2576
2577         if (DISPLAY_VER(display) < 13 || display->platform.alderlake_p)
2578                 caps |= INTEL_PLANE_CAP_TILING_Y;
2579         if (DISPLAY_VER(display) < 12)
2580                 caps |= INTEL_PLANE_CAP_TILING_Yf;
2581         if (HAS_4TILE(display))
2582                 caps |= INTEL_PLANE_CAP_TILING_4;
2583
2584         if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(i915))
2585                 return caps;
2586
2587         if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
2588                 caps |= INTEL_PLANE_CAP_CCS_RC;
2589                 if (DISPLAY_VER(display) >= 12)
2590                         caps |= INTEL_PLANE_CAP_CCS_RC_CC;
2591         }
2592
2593         if (tgl_plane_has_mc_ccs(i915, plane_id))
2594                 caps |= INTEL_PLANE_CAP_CCS_MC;
2595
2596         if (DISPLAY_VER(display) >= 14 && display->platform.dgfx)
2597                 caps |= INTEL_PLANE_CAP_NEED64K_PHYS;
2598
2599         return caps;
2600 }
2601
2602 struct intel_plane *
2603 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2604                            enum pipe pipe, enum plane_id plane_id)
2605 {
2606         const struct drm_plane_funcs *plane_funcs;
2607         struct intel_plane *plane;
2608         enum drm_plane_type plane_type;
2609         unsigned int supported_rotations;
2610         unsigned int supported_csc;
2611         const u64 *modifiers;
2612         const u32 *formats;
2613         int num_formats;
2614         int ret;
2615
2616         plane = intel_plane_alloc();
2617         if (IS_ERR(plane))
2618                 return plane;
2619
2620         plane->pipe = pipe;
2621         plane->id = plane_id;
2622         plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2623
2624         intel_fbc_add_plane(skl_plane_fbc(dev_priv, pipe, plane_id), plane);
2625
2626         if (DISPLAY_VER(dev_priv) >= 30) {
2627                 plane->max_width = xe3_plane_max_width;
2628                 plane->max_height = icl_plane_max_height;
2629                 plane->min_cdclk = icl_plane_min_cdclk;
2630         } else if (DISPLAY_VER(dev_priv) >= 11) {
2631                 plane->min_width = icl_plane_min_width;
2632                 if (icl_is_hdr_plane(dev_priv, plane_id))
2633                         plane->max_width = icl_hdr_plane_max_width;
2634                 else
2635                         plane->max_width = icl_sdr_plane_max_width;
2636                 plane->max_height = icl_plane_max_height;
2637                 plane->min_cdclk = icl_plane_min_cdclk;
2638         } else if (DISPLAY_VER(dev_priv) >= 10) {
2639                 plane->max_width = glk_plane_max_width;
2640                 plane->max_height = skl_plane_max_height;
2641                 plane->min_cdclk = glk_plane_min_cdclk;
2642         } else {
2643                 plane->max_width = skl_plane_max_width;
2644                 plane->max_height = skl_plane_max_height;
2645                 plane->min_cdclk = skl_plane_min_cdclk;
2646         }
2647
2648         if (DISPLAY_VER(dev_priv) >= 13)
2649                 plane->max_stride = adl_plane_max_stride;
2650         else
2651                 plane->max_stride = skl_plane_max_stride;
2652
2653         if (DISPLAY_VER(dev_priv) >= 12)
2654                 plane->min_alignment = tgl_plane_min_alignment;
2655         else
2656                 plane->min_alignment = skl_plane_min_alignment;
2657
2658         if (DISPLAY_VER(dev_priv) >= 11) {
2659                 plane->update_noarm = icl_plane_update_noarm;
2660                 plane->update_arm = icl_plane_update_arm;
2661                 plane->disable_arm = icl_plane_disable_arm;
2662         } else {
2663                 plane->update_noarm = skl_plane_update_noarm;
2664                 plane->update_arm = skl_plane_update_arm;
2665                 plane->disable_arm = skl_plane_disable_arm;
2666         }
2667         plane->get_hw_state = skl_plane_get_hw_state;
2668         plane->check_plane = skl_plane_check;
2669
2670         if (plane_id == PLANE_1) {
2671                 plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(dev_priv, 9, 10);
2672                 plane->async_flip = skl_plane_async_flip;
2673                 plane->enable_flip_done = skl_plane_enable_flip_done;
2674                 plane->disable_flip_done = skl_plane_disable_flip_done;
2675         }
2676
2677         if (DISPLAY_VER(dev_priv) >= 11)
2678                 formats = icl_get_plane_formats(dev_priv, pipe,
2679                                                 plane_id, &num_formats);
2680         else if (DISPLAY_VER(dev_priv) >= 10)
2681                 formats = glk_get_plane_formats(dev_priv, pipe,
2682                                                 plane_id, &num_formats);
2683         else
2684                 formats = skl_get_plane_formats(dev_priv, pipe,
2685                                                 plane_id, &num_formats);
2686
2687         if (DISPLAY_VER(dev_priv) >= 12)
2688                 plane_funcs = &tgl_plane_funcs;
2689         else if (DISPLAY_VER(dev_priv) == 11)
2690                 plane_funcs = &icl_plane_funcs;
2691         else
2692                 plane_funcs = &skl_plane_funcs;
2693
2694         if (plane_id == PLANE_1)
2695                 plane_type = DRM_PLANE_TYPE_PRIMARY;
2696         else
2697                 plane_type = DRM_PLANE_TYPE_OVERLAY;
2698
2699         modifiers = intel_fb_plane_get_modifiers(dev_priv,
2700                                                  skl_get_plane_caps(dev_priv, pipe, plane_id));
2701
2702         ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2703                                        0, plane_funcs,
2704                                        formats, num_formats, modifiers,
2705                                        plane_type,
2706                                        "plane %d%c", plane_id + 1,
2707                                        pipe_name(pipe));
2708
2709         kfree(modifiers);
2710
2711         if (ret)
2712                 goto fail;
2713
2714         if (DISPLAY_VER(dev_priv) >= 13)
2715                 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2716         else
2717                 supported_rotations =
2718                         DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2719                         DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2720
2721         if (DISPLAY_VER(dev_priv) >= 11)
2722                 supported_rotations |= DRM_MODE_REFLECT_X;
2723
2724         drm_plane_create_rotation_property(&plane->base,
2725                                            DRM_MODE_ROTATE_0,
2726                                            supported_rotations);
2727
2728         supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2729
2730         if (DISPLAY_VER(dev_priv) >= 10)
2731                 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2732
2733         drm_plane_create_color_properties(&plane->base,
2734                                           supported_csc,
2735                                           BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2736                                           BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2737                                           DRM_COLOR_YCBCR_BT709,
2738                                           DRM_COLOR_YCBCR_LIMITED_RANGE);
2739
2740         drm_plane_create_alpha_property(&plane->base);
2741         drm_plane_create_blend_mode_property(&plane->base,
2742                                              BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2743                                              BIT(DRM_MODE_BLEND_PREMULTI) |
2744                                              BIT(DRM_MODE_BLEND_COVERAGE));
2745
2746         drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2747
2748         if (DISPLAY_VER(dev_priv) >= 12)
2749                 drm_plane_enable_fb_damage_clips(&plane->base);
2750
2751         if (DISPLAY_VER(dev_priv) >= 11)
2752                 drm_plane_create_scaling_filter_property(&plane->base,
2753                                                 BIT(DRM_SCALING_FILTER_DEFAULT) |
2754                                                 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2755
2756         intel_plane_helper_add(plane);
2757
2758         return plane;
2759
2760 fail:
2761         intel_plane_free(plane);
2762
2763         return ERR_PTR(ret);
2764 }
2765
2766 void
2767 skl_get_initial_plane_config(struct intel_crtc *crtc,
2768                              struct intel_initial_plane_config *plane_config)
2769 {
2770         struct intel_display *display = to_intel_display(crtc);
2771         struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2772         struct drm_device *dev = crtc->base.dev;
2773         struct drm_i915_private *dev_priv = to_i915(dev);
2774         struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2775         enum plane_id plane_id = plane->id;
2776         enum pipe pipe;
2777         u32 val, base, offset, stride_mult, tiling, alpha;
2778         int fourcc, pixel_format;
2779         unsigned int aligned_height;
2780         struct drm_framebuffer *fb;
2781         struct intel_framebuffer *intel_fb;
2782         static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
2783
2784         if (!plane->get_hw_state(plane, &pipe))
2785                 return;
2786
2787         drm_WARN_ON(dev, pipe != crtc->pipe);
2788
2789         if (crtc_state->joiner_pipes) {
2790                 drm_dbg_kms(&dev_priv->drm,
2791                             "Unsupported joiner configuration for initial FB\n");
2792                 return;
2793         }
2794
2795         intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2796         if (!intel_fb) {
2797                 drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2798                 return;
2799         }
2800
2801         fb = &intel_fb->base;
2802
2803         fb->dev = dev;
2804
2805         val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2806
2807         if (DISPLAY_VER(dev_priv) >= 11)
2808                 pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL;
2809         else
2810                 pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL;
2811
2812         if (DISPLAY_VER(dev_priv) >= 10) {
2813                 u32 color_ctl;
2814
2815                 color_ctl = intel_de_read(dev_priv, PLANE_COLOR_CTL(pipe, plane_id));
2816                 alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl);
2817         } else {
2818                 alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val);
2819         }
2820
2821         fourcc = skl_format_to_fourcc(pixel_format,
2822                                       val & PLANE_CTL_ORDER_RGBX, alpha);
2823         fb->format = drm_format_info(fourcc);
2824
2825         tiling = val & PLANE_CTL_TILED_MASK;
2826         switch (tiling) {
2827         case PLANE_CTL_TILED_LINEAR:
2828                 fb->modifier = DRM_FORMAT_MOD_LINEAR;
2829                 break;
2830         case PLANE_CTL_TILED_X:
2831                 plane_config->tiling = I915_TILING_X;
2832                 fb->modifier = I915_FORMAT_MOD_X_TILED;
2833                 break;
2834         case PLANE_CTL_TILED_Y:
2835                 plane_config->tiling = I915_TILING_Y;
2836                 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2837                         if (DISPLAY_VER(dev_priv) >= 14)
2838                                 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS;
2839                         else if (DISPLAY_VER(dev_priv) >= 12)
2840                                 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
2841                         else
2842                                 fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
2843                 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2844                         if (DISPLAY_VER(dev_priv) >= 14)
2845                                 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS;
2846                         else
2847                                 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2848                 else
2849                         fb->modifier = I915_FORMAT_MOD_Y_TILED;
2850                 break;
2851         case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
2852                 if (HAS_4TILE(display)) {
2853                         u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
2854                                       PLANE_CTL_CLEAR_COLOR_DISABLE;
2855
2856                         if ((val & rc_mask) == rc_mask)
2857                                 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
2858                         else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2859                                 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
2860                         else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2861                                 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
2862                         else
2863                                 fb->modifier = I915_FORMAT_MOD_4_TILED;
2864                 } else {
2865                         if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2866                                 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2867                         else
2868                                 fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2869                 }
2870                 break;
2871         default:
2872                 MISSING_CASE(tiling);
2873                 goto error;
2874         }
2875
2876         if (!dev_priv->display.params.enable_dpt &&
2877             intel_fb_modifier_uses_dpt(dev_priv, fb->modifier)) {
2878                 drm_dbg_kms(&dev_priv->drm, "DPT disabled, skipping initial FB\n");
2879                 goto error;
2880         }
2881
2882         /*
2883          * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2884          * while i915 HW rotation is clockwise, thats why this swapping.
2885          */
2886         switch (val & PLANE_CTL_ROTATE_MASK) {
2887         case PLANE_CTL_ROTATE_0:
2888                 plane_config->rotation = DRM_MODE_ROTATE_0;
2889                 break;
2890         case PLANE_CTL_ROTATE_90:
2891                 plane_config->rotation = DRM_MODE_ROTATE_270;
2892                 break;
2893         case PLANE_CTL_ROTATE_180:
2894                 plane_config->rotation = DRM_MODE_ROTATE_180;
2895                 break;
2896         case PLANE_CTL_ROTATE_270:
2897                 plane_config->rotation = DRM_MODE_ROTATE_90;
2898                 break;
2899         }
2900
2901         if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
2902                 plane_config->rotation |= DRM_MODE_REFLECT_X;
2903
2904         /* 90/270 degree rotation would require extra work */
2905         if (drm_rotation_90_or_270(plane_config->rotation))
2906                 goto error;
2907
2908         base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK;
2909         plane_config->base = base;
2910
2911         offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2912         drm_WARN_ON(&dev_priv->drm, offset != 0);
2913
2914         val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2915         fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1;
2916         fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1;
2917
2918         val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2919         stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2920
2921         fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult;
2922
2923         aligned_height = intel_fb_align_height(fb, 0, fb->height);
2924
2925         plane_config->size = fb->pitches[0] * aligned_height;
2926
2927         drm_dbg_kms(&dev_priv->drm,
2928                     "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2929                     crtc->base.name, plane->base.name, fb->width, fb->height,
2930                     fb->format->cpp[0] * 8, base, fb->pitches[0],
2931                     plane_config->size);
2932
2933         plane_config->fb = intel_fb;
2934         return;
2935
2936 error:
2937         kfree(intel_fb);
2938 }
2939
2940 bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
2941                                     const struct intel_initial_plane_config *plane_config)
2942 {
2943         struct drm_i915_private *i915 = to_i915(crtc->base.dev);
2944         struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2945         const struct intel_plane_state *plane_state =
2946                 to_intel_plane_state(plane->base.state);
2947         enum plane_id plane_id = plane->id;
2948         enum pipe pipe = crtc->pipe;
2949         u32 base;
2950
2951         if (!plane_state->uapi.visible)
2952                 return false;
2953
2954         base = intel_plane_ggtt_offset(plane_state);
2955
2956         /*
2957          * We may have moved the surface to a different
2958          * part of ggtt, make the plane aware of that.
2959          */
2960         if (plane_config->base == base)
2961                 return false;
2962
2963         intel_de_write(i915, PLANE_SURF(pipe, plane_id), base);
2964
2965         return true;
2966 }
This page took 0.207059 seconds and 4 git commands to generate.