drm/i915/dg2: Tile 4 plane format support
[linux-2.6-microblaze.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_damage_helper.h>
8 #include <drm/drm_fourcc.h>
9 #include <drm/drm_plane_helper.h>
10
11 #include "i915_drv.h"
12 #include "intel_atomic_plane.h"
13 #include "intel_de.h"
14 #include "intel_display_types.h"
15 #include "intel_fb.h"
16 #include "intel_pm.h"
17 #include "intel_psr.h"
18 #include "intel_sprite.h"
19 #include "skl_scaler.h"
20 #include "skl_universal_plane.h"
21 #include "pxp/intel_pxp.h"
22
23 static const u32 skl_plane_formats[] = {
24         DRM_FORMAT_C8,
25         DRM_FORMAT_RGB565,
26         DRM_FORMAT_XRGB8888,
27         DRM_FORMAT_XBGR8888,
28         DRM_FORMAT_ARGB8888,
29         DRM_FORMAT_ABGR8888,
30         DRM_FORMAT_XRGB2101010,
31         DRM_FORMAT_XBGR2101010,
32         DRM_FORMAT_XRGB16161616F,
33         DRM_FORMAT_XBGR16161616F,
34         DRM_FORMAT_YUYV,
35         DRM_FORMAT_YVYU,
36         DRM_FORMAT_UYVY,
37         DRM_FORMAT_VYUY,
38         DRM_FORMAT_XYUV8888,
39 };
40
41 static const u32 skl_planar_formats[] = {
42         DRM_FORMAT_C8,
43         DRM_FORMAT_RGB565,
44         DRM_FORMAT_XRGB8888,
45         DRM_FORMAT_XBGR8888,
46         DRM_FORMAT_ARGB8888,
47         DRM_FORMAT_ABGR8888,
48         DRM_FORMAT_XRGB2101010,
49         DRM_FORMAT_XBGR2101010,
50         DRM_FORMAT_XRGB16161616F,
51         DRM_FORMAT_XBGR16161616F,
52         DRM_FORMAT_YUYV,
53         DRM_FORMAT_YVYU,
54         DRM_FORMAT_UYVY,
55         DRM_FORMAT_VYUY,
56         DRM_FORMAT_NV12,
57         DRM_FORMAT_XYUV8888,
58 };
59
60 static const u32 glk_planar_formats[] = {
61         DRM_FORMAT_C8,
62         DRM_FORMAT_RGB565,
63         DRM_FORMAT_XRGB8888,
64         DRM_FORMAT_XBGR8888,
65         DRM_FORMAT_ARGB8888,
66         DRM_FORMAT_ABGR8888,
67         DRM_FORMAT_XRGB2101010,
68         DRM_FORMAT_XBGR2101010,
69         DRM_FORMAT_XRGB16161616F,
70         DRM_FORMAT_XBGR16161616F,
71         DRM_FORMAT_YUYV,
72         DRM_FORMAT_YVYU,
73         DRM_FORMAT_UYVY,
74         DRM_FORMAT_VYUY,
75         DRM_FORMAT_NV12,
76         DRM_FORMAT_XYUV8888,
77         DRM_FORMAT_P010,
78         DRM_FORMAT_P012,
79         DRM_FORMAT_P016,
80 };
81
82 static const u32 icl_sdr_y_plane_formats[] = {
83         DRM_FORMAT_C8,
84         DRM_FORMAT_RGB565,
85         DRM_FORMAT_XRGB8888,
86         DRM_FORMAT_XBGR8888,
87         DRM_FORMAT_ARGB8888,
88         DRM_FORMAT_ABGR8888,
89         DRM_FORMAT_XRGB2101010,
90         DRM_FORMAT_XBGR2101010,
91         DRM_FORMAT_ARGB2101010,
92         DRM_FORMAT_ABGR2101010,
93         DRM_FORMAT_YUYV,
94         DRM_FORMAT_YVYU,
95         DRM_FORMAT_UYVY,
96         DRM_FORMAT_VYUY,
97         DRM_FORMAT_Y210,
98         DRM_FORMAT_Y212,
99         DRM_FORMAT_Y216,
100         DRM_FORMAT_XYUV8888,
101         DRM_FORMAT_XVYU2101010,
102         DRM_FORMAT_XVYU12_16161616,
103         DRM_FORMAT_XVYU16161616,
104 };
105
106 static const u32 icl_sdr_uv_plane_formats[] = {
107         DRM_FORMAT_C8,
108         DRM_FORMAT_RGB565,
109         DRM_FORMAT_XRGB8888,
110         DRM_FORMAT_XBGR8888,
111         DRM_FORMAT_ARGB8888,
112         DRM_FORMAT_ABGR8888,
113         DRM_FORMAT_XRGB2101010,
114         DRM_FORMAT_XBGR2101010,
115         DRM_FORMAT_ARGB2101010,
116         DRM_FORMAT_ABGR2101010,
117         DRM_FORMAT_YUYV,
118         DRM_FORMAT_YVYU,
119         DRM_FORMAT_UYVY,
120         DRM_FORMAT_VYUY,
121         DRM_FORMAT_NV12,
122         DRM_FORMAT_P010,
123         DRM_FORMAT_P012,
124         DRM_FORMAT_P016,
125         DRM_FORMAT_Y210,
126         DRM_FORMAT_Y212,
127         DRM_FORMAT_Y216,
128         DRM_FORMAT_XYUV8888,
129         DRM_FORMAT_XVYU2101010,
130         DRM_FORMAT_XVYU12_16161616,
131         DRM_FORMAT_XVYU16161616,
132 };
133
134 static const u32 icl_hdr_plane_formats[] = {
135         DRM_FORMAT_C8,
136         DRM_FORMAT_RGB565,
137         DRM_FORMAT_XRGB8888,
138         DRM_FORMAT_XBGR8888,
139         DRM_FORMAT_ARGB8888,
140         DRM_FORMAT_ABGR8888,
141         DRM_FORMAT_XRGB2101010,
142         DRM_FORMAT_XBGR2101010,
143         DRM_FORMAT_ARGB2101010,
144         DRM_FORMAT_ABGR2101010,
145         DRM_FORMAT_XRGB16161616F,
146         DRM_FORMAT_XBGR16161616F,
147         DRM_FORMAT_ARGB16161616F,
148         DRM_FORMAT_ABGR16161616F,
149         DRM_FORMAT_YUYV,
150         DRM_FORMAT_YVYU,
151         DRM_FORMAT_UYVY,
152         DRM_FORMAT_VYUY,
153         DRM_FORMAT_NV12,
154         DRM_FORMAT_P010,
155         DRM_FORMAT_P012,
156         DRM_FORMAT_P016,
157         DRM_FORMAT_Y210,
158         DRM_FORMAT_Y212,
159         DRM_FORMAT_Y216,
160         DRM_FORMAT_XYUV8888,
161         DRM_FORMAT_XVYU2101010,
162         DRM_FORMAT_XVYU12_16161616,
163         DRM_FORMAT_XVYU16161616,
164 };
165
166 int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
167 {
168         switch (format) {
169         case PLANE_CTL_FORMAT_RGB_565:
170                 return DRM_FORMAT_RGB565;
171         case PLANE_CTL_FORMAT_NV12:
172                 return DRM_FORMAT_NV12;
173         case PLANE_CTL_FORMAT_XYUV:
174                 return DRM_FORMAT_XYUV8888;
175         case PLANE_CTL_FORMAT_P010:
176                 return DRM_FORMAT_P010;
177         case PLANE_CTL_FORMAT_P012:
178                 return DRM_FORMAT_P012;
179         case PLANE_CTL_FORMAT_P016:
180                 return DRM_FORMAT_P016;
181         case PLANE_CTL_FORMAT_Y210:
182                 return DRM_FORMAT_Y210;
183         case PLANE_CTL_FORMAT_Y212:
184                 return DRM_FORMAT_Y212;
185         case PLANE_CTL_FORMAT_Y216:
186                 return DRM_FORMAT_Y216;
187         case PLANE_CTL_FORMAT_Y410:
188                 return DRM_FORMAT_XVYU2101010;
189         case PLANE_CTL_FORMAT_Y412:
190                 return DRM_FORMAT_XVYU12_16161616;
191         case PLANE_CTL_FORMAT_Y416:
192                 return DRM_FORMAT_XVYU16161616;
193         default:
194         case PLANE_CTL_FORMAT_XRGB_8888:
195                 if (rgb_order) {
196                         if (alpha)
197                                 return DRM_FORMAT_ABGR8888;
198                         else
199                                 return DRM_FORMAT_XBGR8888;
200                 } else {
201                         if (alpha)
202                                 return DRM_FORMAT_ARGB8888;
203                         else
204                                 return DRM_FORMAT_XRGB8888;
205                 }
206         case PLANE_CTL_FORMAT_XRGB_2101010:
207                 if (rgb_order) {
208                         if (alpha)
209                                 return DRM_FORMAT_ABGR2101010;
210                         else
211                                 return DRM_FORMAT_XBGR2101010;
212                 } else {
213                         if (alpha)
214                                 return DRM_FORMAT_ARGB2101010;
215                         else
216                                 return DRM_FORMAT_XRGB2101010;
217                 }
218         case PLANE_CTL_FORMAT_XRGB_16161616F:
219                 if (rgb_order) {
220                         if (alpha)
221                                 return DRM_FORMAT_ABGR16161616F;
222                         else
223                                 return DRM_FORMAT_XBGR16161616F;
224                 } else {
225                         if (alpha)
226                                 return DRM_FORMAT_ARGB16161616F;
227                         else
228                                 return DRM_FORMAT_XRGB16161616F;
229                 }
230         }
231 }
232
233 static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
234 {
235         if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
236                 return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
237         else
238                 return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
239 }
240
241 bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
242                          enum plane_id plane_id)
243 {
244         return DISPLAY_VER(dev_priv) >= 11 &&
245                 icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
246 }
247
248 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
249 {
250         return DISPLAY_VER(dev_priv) >= 11 &&
251                 icl_hdr_plane_mask() & BIT(plane_id);
252 }
253
254 static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
255                                const struct intel_plane_state *plane_state)
256 {
257         unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
258
259         /* two pixels per clock */
260         return DIV_ROUND_UP(pixel_rate, 2);
261 }
262
263 static void
264 glk_plane_ratio(const struct intel_plane_state *plane_state,
265                 unsigned int *num, unsigned int *den)
266 {
267         const struct drm_framebuffer *fb = plane_state->hw.fb;
268
269         if (fb->format->cpp[0] == 8) {
270                 *num = 10;
271                 *den = 8;
272         } else {
273                 *num = 1;
274                 *den = 1;
275         }
276 }
277
278 static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
279                                const struct intel_plane_state *plane_state)
280 {
281         unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
282         unsigned int num, den;
283
284         glk_plane_ratio(plane_state, &num, &den);
285
286         /* two pixels per clock */
287         return DIV_ROUND_UP(pixel_rate * num, 2 * den);
288 }
289
290 static void
291 skl_plane_ratio(const struct intel_plane_state *plane_state,
292                 unsigned int *num, unsigned int *den)
293 {
294         const struct drm_framebuffer *fb = plane_state->hw.fb;
295
296         if (fb->format->cpp[0] == 8) {
297                 *num = 9;
298                 *den = 8;
299         } else {
300                 *num = 1;
301                 *den = 1;
302         }
303 }
304
305 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
306                                const struct intel_plane_state *plane_state)
307 {
308         unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
309         unsigned int num, den;
310
311         skl_plane_ratio(plane_state, &num, &den);
312
313         return DIV_ROUND_UP(pixel_rate * num, den);
314 }
315
316 static int skl_plane_max_width(const struct drm_framebuffer *fb,
317                                int color_plane,
318                                unsigned int rotation)
319 {
320         int cpp = fb->format->cpp[color_plane];
321
322         switch (fb->modifier) {
323         case DRM_FORMAT_MOD_LINEAR:
324         case I915_FORMAT_MOD_X_TILED:
325                 /*
326                  * Validated limit is 4k, but has 5k should
327                  * work apart from the following features:
328                  * - Ytile (already limited to 4k)
329                  * - FP16 (already limited to 4k)
330                  * - render compression (already limited to 4k)
331                  * - KVMR sprite and cursor (don't care)
332                  * - horizontal panning (TODO verify this)
333                  * - pipe and plane scaling (TODO verify this)
334                  */
335                 if (cpp == 8)
336                         return 4096;
337                 else
338                         return 5120;
339         case I915_FORMAT_MOD_Y_TILED_CCS:
340         case I915_FORMAT_MOD_Yf_TILED_CCS:
341         case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
342                 /* FIXME AUX plane? */
343         case I915_FORMAT_MOD_Y_TILED:
344         case I915_FORMAT_MOD_Yf_TILED:
345                 if (cpp == 8)
346                         return 2048;
347                 else
348                         return 4096;
349         default:
350                 MISSING_CASE(fb->modifier);
351                 return 2048;
352         }
353 }
354
355 static int glk_plane_max_width(const struct drm_framebuffer *fb,
356                                int color_plane,
357                                unsigned int rotation)
358 {
359         int cpp = fb->format->cpp[color_plane];
360
361         switch (fb->modifier) {
362         case DRM_FORMAT_MOD_LINEAR:
363         case I915_FORMAT_MOD_X_TILED:
364                 if (cpp == 8)
365                         return 4096;
366                 else
367                         return 5120;
368         case I915_FORMAT_MOD_Y_TILED_CCS:
369         case I915_FORMAT_MOD_Yf_TILED_CCS:
370                 /* FIXME AUX plane? */
371         case I915_FORMAT_MOD_Y_TILED:
372         case I915_FORMAT_MOD_Yf_TILED:
373                 if (cpp == 8)
374                         return 2048;
375                 else
376                         return 5120;
377         default:
378                 MISSING_CASE(fb->modifier);
379                 return 2048;
380         }
381 }
382
383 static int icl_plane_min_width(const struct drm_framebuffer *fb,
384                                int color_plane,
385                                unsigned int rotation)
386 {
387         /* Wa_14011264657, Wa_14011050563: gen11+ */
388         switch (fb->format->format) {
389         case DRM_FORMAT_C8:
390                 return 18;
391         case DRM_FORMAT_RGB565:
392                 return 10;
393         case DRM_FORMAT_XRGB8888:
394         case DRM_FORMAT_XBGR8888:
395         case DRM_FORMAT_ARGB8888:
396         case DRM_FORMAT_ABGR8888:
397         case DRM_FORMAT_XRGB2101010:
398         case DRM_FORMAT_XBGR2101010:
399         case DRM_FORMAT_ARGB2101010:
400         case DRM_FORMAT_ABGR2101010:
401         case DRM_FORMAT_XVYU2101010:
402         case DRM_FORMAT_Y212:
403         case DRM_FORMAT_Y216:
404                 return 6;
405         case DRM_FORMAT_NV12:
406                 return 20;
407         case DRM_FORMAT_P010:
408         case DRM_FORMAT_P012:
409         case DRM_FORMAT_P016:
410                 return 12;
411         case DRM_FORMAT_XRGB16161616F:
412         case DRM_FORMAT_XBGR16161616F:
413         case DRM_FORMAT_ARGB16161616F:
414         case DRM_FORMAT_ABGR16161616F:
415         case DRM_FORMAT_XVYU12_16161616:
416         case DRM_FORMAT_XVYU16161616:
417                 return 4;
418         default:
419                 return 1;
420         }
421 }
422
423 static int icl_plane_max_width(const struct drm_framebuffer *fb,
424                                int color_plane,
425                                unsigned int rotation)
426 {
427         return 5120;
428 }
429
430 static int skl_plane_max_height(const struct drm_framebuffer *fb,
431                                 int color_plane,
432                                 unsigned int rotation)
433 {
434         return 4096;
435 }
436
437 static int icl_plane_max_height(const struct drm_framebuffer *fb,
438                                 int color_plane,
439                                 unsigned int rotation)
440 {
441         return 4320;
442 }
443
444 static unsigned int
445 skl_plane_max_stride(struct intel_plane *plane,
446                      u32 pixel_format, u64 modifier,
447                      unsigned int rotation)
448 {
449         struct drm_i915_private *i915 = to_i915(plane->base.dev);
450         const struct drm_format_info *info = drm_format_info(pixel_format);
451         int cpp = info->cpp[0];
452         int max_horizontal_pixels = 8192;
453         int max_stride_bytes;
454
455         if (DISPLAY_VER(i915) >= 13) {
456                 /*
457                  * The stride in bytes must not exceed of the size
458                  * of 128K bytes. For pixel formats of 64bpp will allow
459                  * for a 16K pixel surface.
460                  */
461                 max_stride_bytes = 131072;
462                 if (cpp == 8)
463                         max_horizontal_pixels = 16384;
464                 else
465                         max_horizontal_pixels = 65536;
466         } else {
467                 /*
468                  * "The stride in bytes must not exceed the
469                  * of the size of 8K pixels and 32K bytes."
470                  */
471                 max_stride_bytes = 32768;
472         }
473
474         if (drm_rotation_90_or_270(rotation))
475                 return min(max_horizontal_pixels, max_stride_bytes / cpp);
476         else
477                 return min(max_horizontal_pixels * cpp, max_stride_bytes);
478 }
479
480
481 /* Preoffset values for YUV to RGB Conversion */
482 #define PREOFF_YUV_TO_RGB_HI            0x1800
483 #define PREOFF_YUV_TO_RGB_ME            0x0000
484 #define PREOFF_YUV_TO_RGB_LO            0x1800
485
486 #define  ROFF(x)          (((x) & 0xffff) << 16)
487 #define  GOFF(x)          (((x) & 0xffff) << 0)
488 #define  BOFF(x)          (((x) & 0xffff) << 16)
489
490 /*
491  * Programs the input color space conversion stage for ICL HDR planes.
492  * Note that it is assumed that this stage always happens after YUV
493  * range correction. Thus, the input to this stage is assumed to be
494  * in full-range YCbCr.
495  */
496 static void
497 icl_program_input_csc(struct intel_plane *plane,
498                       const struct intel_crtc_state *crtc_state,
499                       const struct intel_plane_state *plane_state)
500 {
501         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
502         enum pipe pipe = plane->pipe;
503         enum plane_id plane_id = plane->id;
504
505         static const u16 input_csc_matrix[][9] = {
506                 /*
507                  * BT.601 full range YCbCr -> full range RGB
508                  * The matrix required is :
509                  * [1.000, 0.000, 1.371,
510                  *  1.000, -0.336, -0.698,
511                  *  1.000, 1.732, 0.0000]
512                  */
513                 [DRM_COLOR_YCBCR_BT601] = {
514                         0x7AF8, 0x7800, 0x0,
515                         0x8B28, 0x7800, 0x9AC0,
516                         0x0, 0x7800, 0x7DD8,
517                 },
518                 /*
519                  * BT.709 full range YCbCr -> full range RGB
520                  * The matrix required is :
521                  * [1.000, 0.000, 1.574,
522                  *  1.000, -0.187, -0.468,
523                  *  1.000, 1.855, 0.0000]
524                  */
525                 [DRM_COLOR_YCBCR_BT709] = {
526                         0x7C98, 0x7800, 0x0,
527                         0x9EF8, 0x7800, 0xAC00,
528                         0x0, 0x7800,  0x7ED8,
529                 },
530                 /*
531                  * BT.2020 full range YCbCr -> full range RGB
532                  * The matrix required is :
533                  * [1.000, 0.000, 1.474,
534                  *  1.000, -0.1645, -0.5713,
535                  *  1.000, 1.8814, 0.0000]
536                  */
537                 [DRM_COLOR_YCBCR_BT2020] = {
538                         0x7BC8, 0x7800, 0x0,
539                         0x8928, 0x7800, 0xAA88,
540                         0x0, 0x7800, 0x7F10,
541                 },
542         };
543         const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
544
545         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
546                           ROFF(csc[0]) | GOFF(csc[1]));
547         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
548                           BOFF(csc[2]));
549         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
550                           ROFF(csc[3]) | GOFF(csc[4]));
551         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
552                           BOFF(csc[5]));
553         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
554                           ROFF(csc[6]) | GOFF(csc[7]));
555         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
556                           BOFF(csc[8]));
557
558         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
559                           PREOFF_YUV_TO_RGB_HI);
560         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
561                           PREOFF_YUV_TO_RGB_ME);
562         intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
563                           PREOFF_YUV_TO_RGB_LO);
564         intel_de_write_fw(dev_priv,
565                           PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
566         intel_de_write_fw(dev_priv,
567                           PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
568         intel_de_write_fw(dev_priv,
569                           PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
570 }
571
572 static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
573                                           int color_plane, unsigned int rotation)
574 {
575         /*
576          * The stride is either expressed as a multiple of 64 bytes chunks for
577          * linear buffers or in number of tiles for tiled buffers.
578          */
579         if (is_surface_linear(fb, color_plane))
580                 return 64;
581         else if (drm_rotation_90_or_270(rotation))
582                 return intel_tile_height(fb, color_plane);
583         else
584                 return intel_tile_width_bytes(fb, color_plane);
585 }
586
587 static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
588                             int color_plane)
589 {
590         const struct drm_framebuffer *fb = plane_state->hw.fb;
591         unsigned int rotation = plane_state->hw.rotation;
592         u32 stride = plane_state->view.color_plane[color_plane].scanout_stride;
593
594         if (color_plane >= fb->format->num_planes)
595                 return 0;
596
597         return stride / skl_plane_stride_mult(fb, color_plane, rotation);
598 }
599
600 static void
601 skl_plane_disable_arm(struct intel_plane *plane,
602                       const struct intel_crtc_state *crtc_state)
603 {
604         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
605         enum plane_id plane_id = plane->id;
606         enum pipe pipe = plane->pipe;
607         unsigned long irqflags;
608
609         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
610
611         if (icl_is_hdr_plane(dev_priv, plane_id))
612                 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
613
614         skl_write_plane_wm(plane, crtc_state);
615
616         intel_psr2_disable_plane_sel_fetch(plane, crtc_state);
617         intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
618         intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
619
620         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
621 }
622
623 static bool
624 skl_plane_get_hw_state(struct intel_plane *plane,
625                        enum pipe *pipe)
626 {
627         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
628         enum intel_display_power_domain power_domain;
629         enum plane_id plane_id = plane->id;
630         intel_wakeref_t wakeref;
631         bool ret;
632
633         power_domain = POWER_DOMAIN_PIPE(plane->pipe);
634         wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
635         if (!wakeref)
636                 return false;
637
638         ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
639
640         *pipe = plane->pipe;
641
642         intel_display_power_put(dev_priv, power_domain, wakeref);
643
644         return ret;
645 }
646
647 static u32 skl_plane_ctl_format(u32 pixel_format)
648 {
649         switch (pixel_format) {
650         case DRM_FORMAT_C8:
651                 return PLANE_CTL_FORMAT_INDEXED;
652         case DRM_FORMAT_RGB565:
653                 return PLANE_CTL_FORMAT_RGB_565;
654         case DRM_FORMAT_XBGR8888:
655         case DRM_FORMAT_ABGR8888:
656                 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
657         case DRM_FORMAT_XRGB8888:
658         case DRM_FORMAT_ARGB8888:
659                 return PLANE_CTL_FORMAT_XRGB_8888;
660         case DRM_FORMAT_XBGR2101010:
661         case DRM_FORMAT_ABGR2101010:
662                 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
663         case DRM_FORMAT_XRGB2101010:
664         case DRM_FORMAT_ARGB2101010:
665                 return PLANE_CTL_FORMAT_XRGB_2101010;
666         case DRM_FORMAT_XBGR16161616F:
667         case DRM_FORMAT_ABGR16161616F:
668                 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
669         case DRM_FORMAT_XRGB16161616F:
670         case DRM_FORMAT_ARGB16161616F:
671                 return PLANE_CTL_FORMAT_XRGB_16161616F;
672         case DRM_FORMAT_XYUV8888:
673                 return PLANE_CTL_FORMAT_XYUV;
674         case DRM_FORMAT_YUYV:
675                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
676         case DRM_FORMAT_YVYU:
677                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
678         case DRM_FORMAT_UYVY:
679                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
680         case DRM_FORMAT_VYUY:
681                 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
682         case DRM_FORMAT_NV12:
683                 return PLANE_CTL_FORMAT_NV12;
684         case DRM_FORMAT_P010:
685                 return PLANE_CTL_FORMAT_P010;
686         case DRM_FORMAT_P012:
687                 return PLANE_CTL_FORMAT_P012;
688         case DRM_FORMAT_P016:
689                 return PLANE_CTL_FORMAT_P016;
690         case DRM_FORMAT_Y210:
691                 return PLANE_CTL_FORMAT_Y210;
692         case DRM_FORMAT_Y212:
693                 return PLANE_CTL_FORMAT_Y212;
694         case DRM_FORMAT_Y216:
695                 return PLANE_CTL_FORMAT_Y216;
696         case DRM_FORMAT_XVYU2101010:
697                 return PLANE_CTL_FORMAT_Y410;
698         case DRM_FORMAT_XVYU12_16161616:
699                 return PLANE_CTL_FORMAT_Y412;
700         case DRM_FORMAT_XVYU16161616:
701                 return PLANE_CTL_FORMAT_Y416;
702         default:
703                 MISSING_CASE(pixel_format);
704         }
705
706         return 0;
707 }
708
709 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
710 {
711         if (!plane_state->hw.fb->format->has_alpha)
712                 return PLANE_CTL_ALPHA_DISABLE;
713
714         switch (plane_state->hw.pixel_blend_mode) {
715         case DRM_MODE_BLEND_PIXEL_NONE:
716                 return PLANE_CTL_ALPHA_DISABLE;
717         case DRM_MODE_BLEND_PREMULTI:
718                 return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
719         case DRM_MODE_BLEND_COVERAGE:
720                 return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
721         default:
722                 MISSING_CASE(plane_state->hw.pixel_blend_mode);
723                 return PLANE_CTL_ALPHA_DISABLE;
724         }
725 }
726
727 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
728 {
729         if (!plane_state->hw.fb->format->has_alpha)
730                 return PLANE_COLOR_ALPHA_DISABLE;
731
732         switch (plane_state->hw.pixel_blend_mode) {
733         case DRM_MODE_BLEND_PIXEL_NONE:
734                 return PLANE_COLOR_ALPHA_DISABLE;
735         case DRM_MODE_BLEND_PREMULTI:
736                 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
737         case DRM_MODE_BLEND_COVERAGE:
738                 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
739         default:
740                 MISSING_CASE(plane_state->hw.pixel_blend_mode);
741                 return PLANE_COLOR_ALPHA_DISABLE;
742         }
743 }
744
745 static u32 skl_plane_ctl_tiling(u64 fb_modifier)
746 {
747         switch (fb_modifier) {
748         case DRM_FORMAT_MOD_LINEAR:
749                 break;
750         case I915_FORMAT_MOD_X_TILED:
751                 return PLANE_CTL_TILED_X;
752         case I915_FORMAT_MOD_Y_TILED:
753                 return PLANE_CTL_TILED_Y;
754         case I915_FORMAT_MOD_4_TILED:
755                 return PLANE_CTL_TILED_4;
756         case I915_FORMAT_MOD_Y_TILED_CCS:
757         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
758                 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
759         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
760                 return PLANE_CTL_TILED_Y |
761                        PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
762                        PLANE_CTL_CLEAR_COLOR_DISABLE;
763         case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
764                 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
765         case I915_FORMAT_MOD_Yf_TILED:
766                 return PLANE_CTL_TILED_YF;
767         case I915_FORMAT_MOD_Yf_TILED_CCS:
768                 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
769         default:
770                 MISSING_CASE(fb_modifier);
771         }
772
773         return 0;
774 }
775
776 static u32 skl_plane_ctl_rotate(unsigned int rotate)
777 {
778         switch (rotate) {
779         case DRM_MODE_ROTATE_0:
780                 break;
781         /*
782          * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
783          * while i915 HW rotation is clockwise, thats why this swapping.
784          */
785         case DRM_MODE_ROTATE_90:
786                 return PLANE_CTL_ROTATE_270;
787         case DRM_MODE_ROTATE_180:
788                 return PLANE_CTL_ROTATE_180;
789         case DRM_MODE_ROTATE_270:
790                 return PLANE_CTL_ROTATE_90;
791         default:
792                 MISSING_CASE(rotate);
793         }
794
795         return 0;
796 }
797
798 static u32 icl_plane_ctl_flip(unsigned int reflect)
799 {
800         switch (reflect) {
801         case 0:
802                 break;
803         case DRM_MODE_REFLECT_X:
804                 return PLANE_CTL_FLIP_HORIZONTAL;
805         case DRM_MODE_REFLECT_Y:
806         default:
807                 MISSING_CASE(reflect);
808         }
809
810         return 0;
811 }
812
813 static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
814 {
815         const struct drm_framebuffer *fb = plane_state->hw.fb;
816
817         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
818                 switch (fb->format->cpp[0]) {
819                 case 2:
820                         return PLANE_CTL_ARB_SLOTS(1);
821                 default:
822                         return PLANE_CTL_ARB_SLOTS(0);
823                 }
824         } else {
825                 switch (fb->format->cpp[0]) {
826                 case 8:
827                         return PLANE_CTL_ARB_SLOTS(3);
828                 case 4:
829                         return PLANE_CTL_ARB_SLOTS(1);
830                 default:
831                         return PLANE_CTL_ARB_SLOTS(0);
832                 }
833         }
834 }
835
836 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
837 {
838         struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
839         u32 plane_ctl = 0;
840
841         if (DISPLAY_VER(dev_priv) >= 10)
842                 return plane_ctl;
843
844         if (crtc_state->gamma_enable)
845                 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
846
847         if (crtc_state->csc_enable)
848                 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
849
850         return plane_ctl;
851 }
852
853 static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
854                          const struct intel_plane_state *plane_state)
855 {
856         struct drm_i915_private *dev_priv =
857                 to_i915(plane_state->uapi.plane->dev);
858         const struct drm_framebuffer *fb = plane_state->hw.fb;
859         unsigned int rotation = plane_state->hw.rotation;
860         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
861         u32 plane_ctl;
862
863         plane_ctl = PLANE_CTL_ENABLE;
864
865         if (DISPLAY_VER(dev_priv) < 10) {
866                 plane_ctl |= skl_plane_ctl_alpha(plane_state);
867                 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
868
869                 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
870                         plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
871
872                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
873                         plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
874         }
875
876         plane_ctl |= skl_plane_ctl_format(fb->format->format);
877         plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
878         plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
879
880         if (DISPLAY_VER(dev_priv) >= 11)
881                 plane_ctl |= icl_plane_ctl_flip(rotation &
882                                                 DRM_MODE_REFLECT_MASK);
883
884         if (key->flags & I915_SET_COLORKEY_DESTINATION)
885                 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
886         else if (key->flags & I915_SET_COLORKEY_SOURCE)
887                 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
888
889         /* Wa_22012358565:adl-p */
890         if (DISPLAY_VER(dev_priv) == 13)
891                 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
892
893         return plane_ctl;
894 }
895
896 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
897 {
898         struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
899         u32 plane_color_ctl = 0;
900
901         if (DISPLAY_VER(dev_priv) >= 11)
902                 return plane_color_ctl;
903
904         if (crtc_state->gamma_enable)
905                 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
906
907         if (crtc_state->csc_enable)
908                 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
909
910         return plane_color_ctl;
911 }
912
913 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
914                                const struct intel_plane_state *plane_state)
915 {
916         struct drm_i915_private *dev_priv =
917                 to_i915(plane_state->uapi.plane->dev);
918         const struct drm_framebuffer *fb = plane_state->hw.fb;
919         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
920         u32 plane_color_ctl = 0;
921
922         plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
923         plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
924
925         if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
926                 switch (plane_state->hw.color_encoding) {
927                 case DRM_COLOR_YCBCR_BT709:
928                         plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
929                         break;
930                 case DRM_COLOR_YCBCR_BT2020:
931                         plane_color_ctl |=
932                                 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
933                         break;
934                 default:
935                         plane_color_ctl |=
936                                 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
937                 }
938                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
939                         plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
940         } else if (fb->format->is_yuv) {
941                 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
942                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
943                         plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
944         }
945
946         if (plane_state->force_black)
947                 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
948
949         return plane_color_ctl;
950 }
951
952 static u32 skl_surf_address(const struct intel_plane_state *plane_state,
953                             int color_plane)
954 {
955         const struct drm_framebuffer *fb = plane_state->hw.fb;
956         u32 offset = plane_state->view.color_plane[color_plane].offset;
957
958         if (intel_fb_uses_dpt(fb)) {
959                 /*
960                  * The DPT object contains only one vma, so the VMA's offset
961                  * within the DPT is always 0.
962                  */
963                 WARN_ON(plane_state->dpt_vma->node.start);
964                 WARN_ON(offset & 0x1fffff);
965                 return offset >> 9;
966         } else {
967                 WARN_ON(offset & 0xfff);
968                 return offset;
969         }
970 }
971
972 static u32 skl_plane_surf(const struct intel_plane_state *plane_state,
973                           int color_plane)
974 {
975         u32 plane_surf;
976
977         plane_surf = intel_plane_ggtt_offset(plane_state) +
978                 skl_surf_address(plane_state, color_plane);
979
980         if (plane_state->decrypt)
981                 plane_surf |= PLANE_SURF_DECRYPT;
982
983         return plane_surf;
984 }
985
986 static void icl_plane_csc_load_black(struct intel_plane *plane)
987 {
988         struct drm_i915_private *i915 = to_i915(plane->base.dev);
989         enum plane_id plane_id = plane->id;
990         enum pipe pipe = plane->pipe;
991
992         intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 0), 0);
993         intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 1), 0);
994
995         intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 2), 0);
996         intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 3), 0);
997
998         intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 4), 0);
999         intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 5), 0);
1000
1001         intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0);
1002         intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0);
1003         intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0);
1004
1005         intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0);
1006         intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0);
1007         intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
1008 }
1009
1010 static void
1011 skl_program_plane_noarm(struct intel_plane *plane,
1012                         const struct intel_crtc_state *crtc_state,
1013                         const struct intel_plane_state *plane_state,
1014                         int color_plane)
1015 {
1016         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1017         enum plane_id plane_id = plane->id;
1018         enum pipe pipe = plane->pipe;
1019         u32 stride = skl_plane_stride(plane_state, color_plane);
1020         const struct drm_framebuffer *fb = plane_state->hw.fb;
1021         int crtc_x = plane_state->uapi.dst.x1;
1022         int crtc_y = plane_state->uapi.dst.y1;
1023         u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1024         u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1025         unsigned long irqflags;
1026
1027         /* Sizes are 0 based */
1028         src_w--;
1029         src_h--;
1030
1031         /* The scaler will handle the output position */
1032         if (plane_state->scaler_id >= 0) {
1033                 crtc_x = 0;
1034                 crtc_y = 0;
1035         }
1036
1037         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1038
1039         /*
1040          * FIXME: pxp session invalidation can hit any time even at time of commit
1041          * or after the commit, display content will be garbage.
1042          */
1043         if (plane_state->force_black)
1044                 icl_plane_csc_load_black(plane);
1045
1046         intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
1047         intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
1048                           (crtc_y << 16) | crtc_x);
1049         intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
1050                           (src_h << 16) | src_w);
1051
1052         if (icl_is_hdr_plane(dev_priv, plane_id))
1053                 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
1054                                   plane_state->cus_ctl);
1055
1056         if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1057                 icl_program_input_csc(plane, crtc_state, plane_state);
1058
1059         if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier))
1060                 intel_uncore_write64_fw(&dev_priv->uncore,
1061                                         PLANE_CC_VAL(pipe, plane_id), plane_state->ccval);
1062
1063         skl_write_plane_wm(plane, crtc_state);
1064
1065         intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
1066
1067         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1068 }
1069
1070 static void
1071 skl_program_plane_arm(struct intel_plane *plane,
1072                       const struct intel_crtc_state *crtc_state,
1073                       const struct intel_plane_state *plane_state,
1074                       int color_plane)
1075 {
1076         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1077         enum plane_id plane_id = plane->id;
1078         enum pipe pipe = plane->pipe;
1079         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1080         const struct drm_framebuffer *fb = plane_state->hw.fb;
1081         int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1082         u32 x = plane_state->view.color_plane[color_plane].x;
1083         u32 y = plane_state->view.color_plane[color_plane].y;
1084         u32 keymsk, keymax, aux_dist = 0, plane_color_ctl = 0;
1085         u8 alpha = plane_state->hw.alpha >> 8;
1086         u32 plane_ctl = plane_state->ctl;
1087         unsigned long irqflags;
1088
1089         plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1090
1091         if (DISPLAY_VER(dev_priv) >= 10)
1092                 plane_color_ctl = plane_state->color_ctl |
1093                         glk_plane_color_ctl_crtc(crtc_state);
1094
1095         keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
1096
1097         keymsk = key->channel_mask & 0x7ffffff;
1098         if (alpha < 0xff)
1099                 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
1100
1101         if (aux_plane) {
1102                 aux_dist = skl_surf_address(plane_state, aux_plane) -
1103                         skl_surf_address(plane_state, color_plane);
1104
1105                 if (DISPLAY_VER(dev_priv) < 12)
1106                         aux_dist |= skl_plane_stride(plane_state, aux_plane);
1107         }
1108
1109         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1110
1111         intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
1112                           key->min_value);
1113         intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
1114         intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
1115
1116         intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1117                           (y << 16) | x);
1118
1119         intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
1120
1121         if (DISPLAY_VER(dev_priv) < 11)
1122                 intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
1123                                   (plane_state->view.color_plane[1].y << 16) |
1124                                    plane_state->view.color_plane[1].x);
1125
1126         if (DISPLAY_VER(dev_priv) >= 10)
1127                 intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
1128
1129         /*
1130          * Enable the scaler before the plane so that we don't
1131          * get a catastrophic underrun even if the two operations
1132          * end up happening in two different frames.
1133          *
1134          * TODO: split into noarm+arm pair
1135          */
1136         if (plane_state->scaler_id >= 0)
1137                 skl_program_plane_scaler(plane, crtc_state, plane_state);
1138
1139         /*
1140          * The control register self-arms if the plane was previously
1141          * disabled. Try to make the plane enable atomic by writing
1142          * the control register just before the surface register.
1143          */
1144         intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1145         intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1146                           skl_plane_surf(plane_state, color_plane));
1147
1148         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1149 }
1150
1151 static void
1152 skl_plane_async_flip(struct intel_plane *plane,
1153                      const struct intel_crtc_state *crtc_state,
1154                      const struct intel_plane_state *plane_state,
1155                      bool async_flip)
1156 {
1157         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1158         unsigned long irqflags;
1159         enum plane_id plane_id = plane->id;
1160         enum pipe pipe = plane->pipe;
1161         u32 plane_ctl = plane_state->ctl;
1162
1163         plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1164
1165         if (async_flip)
1166                 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1167
1168         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1169
1170         intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1171         intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1172                           skl_plane_surf(plane_state, 0));
1173
1174         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1175 }
1176
1177 static void
1178 skl_plane_update_noarm(struct intel_plane *plane,
1179                        const struct intel_crtc_state *crtc_state,
1180                        const struct intel_plane_state *plane_state)
1181 {
1182         int color_plane = 0;
1183
1184         if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1185                 /* Program the UV plane on planar master */
1186                 color_plane = 1;
1187
1188         skl_program_plane_noarm(plane, crtc_state, plane_state, color_plane);
1189 }
1190
1191 static void
1192 skl_plane_update_arm(struct intel_plane *plane,
1193                      const struct intel_crtc_state *crtc_state,
1194                      const struct intel_plane_state *plane_state)
1195 {
1196         int color_plane = 0;
1197
1198         if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1199                 /* Program the UV plane on planar master */
1200                 color_plane = 1;
1201
1202         skl_program_plane_arm(plane, crtc_state, plane_state, color_plane);
1203 }
1204
1205 static bool intel_format_is_p01x(u32 format)
1206 {
1207         switch (format) {
1208         case DRM_FORMAT_P010:
1209         case DRM_FORMAT_P012:
1210         case DRM_FORMAT_P016:
1211                 return true;
1212         default:
1213                 return false;
1214         }
1215 }
1216
1217 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1218                               const struct intel_plane_state *plane_state)
1219 {
1220         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1221         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1222         const struct drm_framebuffer *fb = plane_state->hw.fb;
1223         unsigned int rotation = plane_state->hw.rotation;
1224
1225         if (!fb)
1226                 return 0;
1227
1228         if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1229             intel_fb_is_ccs_modifier(fb->modifier)) {
1230                 drm_dbg_kms(&dev_priv->drm,
1231                             "RC support only with 0/180 degree rotation (%x)\n",
1232                             rotation);
1233                 return -EINVAL;
1234         }
1235
1236         if (rotation & DRM_MODE_REFLECT_X &&
1237             fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1238                 drm_dbg_kms(&dev_priv->drm,
1239                             "horizontal flip is not supported with linear surface formats\n");
1240                 return -EINVAL;
1241         }
1242
1243         if (drm_rotation_90_or_270(rotation)) {
1244                 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
1245                         drm_dbg_kms(&dev_priv->drm,
1246                                     "Y/Yf tiling required for 90/270!\n");
1247                         return -EINVAL;
1248                 }
1249
1250                 /*
1251                  * 90/270 is not allowed with RGB64 16:16:16:16 and
1252                  * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1253                  */
1254                 switch (fb->format->format) {
1255                 case DRM_FORMAT_RGB565:
1256                         if (DISPLAY_VER(dev_priv) >= 11)
1257                                 break;
1258                         fallthrough;
1259                 case DRM_FORMAT_C8:
1260                 case DRM_FORMAT_XRGB16161616F:
1261                 case DRM_FORMAT_XBGR16161616F:
1262                 case DRM_FORMAT_ARGB16161616F:
1263                 case DRM_FORMAT_ABGR16161616F:
1264                 case DRM_FORMAT_Y210:
1265                 case DRM_FORMAT_Y212:
1266                 case DRM_FORMAT_Y216:
1267                 case DRM_FORMAT_XVYU12_16161616:
1268                 case DRM_FORMAT_XVYU16161616:
1269                         drm_dbg_kms(&dev_priv->drm,
1270                                     "Unsupported pixel format %p4cc for 90/270!\n",
1271                                     &fb->format->format);
1272                         return -EINVAL;
1273                 default:
1274                         break;
1275                 }
1276         }
1277
1278         /* Y-tiling is not supported in IF-ID Interlace mode */
1279         if (crtc_state->hw.enable &&
1280             crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1281             fb->modifier != DRM_FORMAT_MOD_LINEAR &&
1282             fb->modifier != I915_FORMAT_MOD_X_TILED) {
1283                 drm_dbg_kms(&dev_priv->drm,
1284                             "Y/Yf tiling not supported in IF-ID mode\n");
1285                 return -EINVAL;
1286         }
1287
1288         /* Wa_1606054188:tgl,adl-s */
1289         if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1290             plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1291             intel_format_is_p01x(fb->format->format)) {
1292                 drm_dbg_kms(&dev_priv->drm,
1293                             "Source color keying not supported with P01x formats\n");
1294                 return -EINVAL;
1295         }
1296
1297         return 0;
1298 }
1299
1300 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1301                                            const struct intel_plane_state *plane_state)
1302 {
1303         struct drm_i915_private *dev_priv =
1304                 to_i915(plane_state->uapi.plane->dev);
1305         int crtc_x = plane_state->uapi.dst.x1;
1306         int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1307         int pipe_src_w = crtc_state->pipe_src_w;
1308
1309         /*
1310          * Display WA #1175: glk
1311          * Planes other than the cursor may cause FIFO underflow and display
1312          * corruption if starting less than 4 pixels from the right edge of
1313          * the screen.
1314          * Besides the above WA fix the similar problem, where planes other
1315          * than the cursor ending less than 4 pixels from the left edge of the
1316          * screen may cause FIFO underflow and display corruption.
1317          */
1318         if (DISPLAY_VER(dev_priv) == 10 &&
1319             (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1320                 drm_dbg_kms(&dev_priv->drm,
1321                             "requested plane X %s position %d invalid (valid range %d-%d)\n",
1322                             crtc_x + crtc_w < 4 ? "end" : "start",
1323                             crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1324                             4, pipe_src_w - 4);
1325                 return -ERANGE;
1326         }
1327
1328         return 0;
1329 }
1330
1331 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1332 {
1333         const struct drm_framebuffer *fb = plane_state->hw.fb;
1334         unsigned int rotation = plane_state->hw.rotation;
1335         int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1336
1337         /* Display WA #1106 */
1338         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1339             src_w & 3 &&
1340             (rotation == DRM_MODE_ROTATE_270 ||
1341              rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1342                 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1343                 return -EINVAL;
1344         }
1345
1346         return 0;
1347 }
1348
1349 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1350                                const struct drm_framebuffer *fb)
1351 {
1352         /*
1353          * We don't yet know the final source width nor
1354          * whether we can use the HQ scaler mode. Assume
1355          * the best case.
1356          * FIXME need to properly check this later.
1357          */
1358         if (DISPLAY_VER(dev_priv) >= 10 ||
1359             !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1360                 return 0x30000 - 1;
1361         else
1362                 return 0x20000 - 1;
1363 }
1364
1365 static int intel_plane_min_width(struct intel_plane *plane,
1366                                  const struct drm_framebuffer *fb,
1367                                  int color_plane,
1368                                  unsigned int rotation)
1369 {
1370         if (plane->min_width)
1371                 return plane->min_width(fb, color_plane, rotation);
1372         else
1373                 return 1;
1374 }
1375
1376 static int intel_plane_max_width(struct intel_plane *plane,
1377                                  const struct drm_framebuffer *fb,
1378                                  int color_plane,
1379                                  unsigned int rotation)
1380 {
1381         if (plane->max_width)
1382                 return plane->max_width(fb, color_plane, rotation);
1383         else
1384                 return INT_MAX;
1385 }
1386
1387 static int intel_plane_max_height(struct intel_plane *plane,
1388                                   const struct drm_framebuffer *fb,
1389                                   int color_plane,
1390                                   unsigned int rotation)
1391 {
1392         if (plane->max_height)
1393                 return plane->max_height(fb, color_plane, rotation);
1394         else
1395                 return INT_MAX;
1396 }
1397
1398 static bool
1399 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1400                                int main_x, int main_y, u32 main_offset,
1401                                int ccs_plane)
1402 {
1403         const struct drm_framebuffer *fb = plane_state->hw.fb;
1404         int aux_x = plane_state->view.color_plane[ccs_plane].x;
1405         int aux_y = plane_state->view.color_plane[ccs_plane].y;
1406         u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1407         u32 alignment = intel_surf_alignment(fb, ccs_plane);
1408         int hsub;
1409         int vsub;
1410
1411         intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1412         while (aux_offset >= main_offset && aux_y <= main_y) {
1413                 int x, y;
1414
1415                 if (aux_x == main_x && aux_y == main_y)
1416                         break;
1417
1418                 if (aux_offset == 0)
1419                         break;
1420
1421                 x = aux_x / hsub;
1422                 y = aux_y / vsub;
1423                 aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1424                                                                plane_state,
1425                                                                ccs_plane,
1426                                                                aux_offset,
1427                                                                aux_offset -
1428                                                                 alignment);
1429                 aux_x = x * hsub + aux_x % hsub;
1430                 aux_y = y * vsub + aux_y % vsub;
1431         }
1432
1433         if (aux_x != main_x || aux_y != main_y)
1434                 return false;
1435
1436         plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1437         plane_state->view.color_plane[ccs_plane].x = aux_x;
1438         plane_state->view.color_plane[ccs_plane].y = aux_y;
1439
1440         return true;
1441 }
1442
1443
1444 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1445                                  int *x, int *y, u32 *offset)
1446 {
1447         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1448         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1449         const struct drm_framebuffer *fb = plane_state->hw.fb;
1450         const int aux_plane = skl_main_to_aux_plane(fb, 0);
1451         const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1452         const u32 alignment = intel_surf_alignment(fb, 0);
1453         const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1454
1455         intel_add_fb_offsets(x, y, plane_state, 0);
1456         *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1457         if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1458                 return -EINVAL;
1459
1460         /*
1461          * AUX surface offset is specified as the distance from the
1462          * main surface offset, and it must be non-negative. Make
1463          * sure that is what we will get.
1464          */
1465         if (aux_plane && *offset > aux_offset)
1466                 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1467                                                             *offset,
1468                                                             aux_offset & ~(alignment - 1));
1469
1470         /*
1471          * When using an X-tiled surface, the plane blows up
1472          * if the x offset + width exceed the stride.
1473          *
1474          * TODO: linear and Y-tiled seem fine, Yf untested,
1475          */
1476         if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1477                 int cpp = fb->format->cpp[0];
1478
1479                 while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
1480                         if (*offset == 0) {
1481                                 drm_dbg_kms(&dev_priv->drm,
1482                                             "Unable to find suitable display surface offset due to X-tiling\n");
1483                                 return -EINVAL;
1484                         }
1485
1486                         *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1487                                                                     *offset,
1488                                                                     *offset - alignment);
1489                 }
1490         }
1491
1492         return 0;
1493 }
1494
1495 static int skl_check_main_surface(struct intel_plane_state *plane_state)
1496 {
1497         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1498         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1499         const struct drm_framebuffer *fb = plane_state->hw.fb;
1500         const unsigned int rotation = plane_state->hw.rotation;
1501         int x = plane_state->uapi.src.x1 >> 16;
1502         int y = plane_state->uapi.src.y1 >> 16;
1503         const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1504         const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1505         const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1506         const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1507         const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1508         const int aux_plane = skl_main_to_aux_plane(fb, 0);
1509         const u32 alignment = intel_surf_alignment(fb, 0);
1510         u32 offset;
1511         int ret;
1512
1513         if (w > max_width || w < min_width || h > max_height) {
1514                 drm_dbg_kms(&dev_priv->drm,
1515                             "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1516                             w, h, min_width, max_width, max_height);
1517                 return -EINVAL;
1518         }
1519
1520         ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1521         if (ret)
1522                 return ret;
1523
1524         /*
1525          * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1526          * they match with the main surface x/y offsets.
1527          */
1528         if (intel_fb_is_ccs_modifier(fb->modifier)) {
1529                 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1530                                                        offset, aux_plane)) {
1531                         if (offset == 0)
1532                                 break;
1533
1534                         offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1535                                                                    offset, offset - alignment);
1536                 }
1537
1538                 if (x != plane_state->view.color_plane[aux_plane].x ||
1539                     y != plane_state->view.color_plane[aux_plane].y) {
1540                         drm_dbg_kms(&dev_priv->drm,
1541                                     "Unable to find suitable display surface offset due to CCS\n");
1542                         return -EINVAL;
1543                 }
1544         }
1545
1546         if (DISPLAY_VER(dev_priv) >= 13)
1547                 drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
1548         else
1549                 drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1550
1551         plane_state->view.color_plane[0].offset = offset;
1552         plane_state->view.color_plane[0].x = x;
1553         plane_state->view.color_plane[0].y = y;
1554
1555         /*
1556          * Put the final coordinates back so that the src
1557          * coordinate checks will see the right values.
1558          */
1559         drm_rect_translate_to(&plane_state->uapi.src,
1560                               x << 16, y << 16);
1561
1562         return 0;
1563 }
1564
1565 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1566 {
1567         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1568         struct drm_i915_private *i915 = to_i915(plane->base.dev);
1569         const struct drm_framebuffer *fb = plane_state->hw.fb;
1570         unsigned int rotation = plane_state->hw.rotation;
1571         int uv_plane = 1;
1572         int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
1573         int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
1574         int x = plane_state->uapi.src.x1 >> 17;
1575         int y = plane_state->uapi.src.y1 >> 17;
1576         int w = drm_rect_width(&plane_state->uapi.src) >> 17;
1577         int h = drm_rect_height(&plane_state->uapi.src) >> 17;
1578         u32 offset;
1579
1580         /* FIXME not quite sure how/if these apply to the chroma plane */
1581         if (w > max_width || h > max_height) {
1582                 drm_dbg_kms(&i915->drm,
1583                             "CbCr source size %dx%d too big (limit %dx%d)\n",
1584                             w, h, max_width, max_height);
1585                 return -EINVAL;
1586         }
1587
1588         intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
1589         offset = intel_plane_compute_aligned_offset(&x, &y,
1590                                                     plane_state, uv_plane);
1591
1592         if (intel_fb_is_ccs_modifier(fb->modifier)) {
1593                 int ccs_plane = main_to_ccs_plane(fb, uv_plane);
1594                 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1595                 u32 alignment = intel_surf_alignment(fb, uv_plane);
1596
1597                 if (offset > aux_offset)
1598                         offset = intel_plane_adjust_aligned_offset(&x, &y,
1599                                                                    plane_state,
1600                                                                    uv_plane,
1601                                                                    offset,
1602                                                                    aux_offset & ~(alignment - 1));
1603
1604                 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1605                                                        offset, ccs_plane)) {
1606                         if (offset == 0)
1607                                 break;
1608
1609                         offset = intel_plane_adjust_aligned_offset(&x, &y,
1610                                                                    plane_state,
1611                                                                    uv_plane,
1612                                                                    offset, offset - alignment);
1613                 }
1614
1615                 if (x != plane_state->view.color_plane[ccs_plane].x ||
1616                     y != plane_state->view.color_plane[ccs_plane].y) {
1617                         drm_dbg_kms(&i915->drm,
1618                                     "Unable to find suitable display surface offset due to CCS\n");
1619                         return -EINVAL;
1620                 }
1621         }
1622
1623         if (DISPLAY_VER(i915) >= 13)
1624                 drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
1625         else
1626                 drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
1627
1628         plane_state->view.color_plane[uv_plane].offset = offset;
1629         plane_state->view.color_plane[uv_plane].x = x;
1630         plane_state->view.color_plane[uv_plane].y = y;
1631
1632         return 0;
1633 }
1634
1635 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
1636 {
1637         const struct drm_framebuffer *fb = plane_state->hw.fb;
1638         int src_x = plane_state->uapi.src.x1 >> 16;
1639         int src_y = plane_state->uapi.src.y1 >> 16;
1640         u32 offset;
1641         int ccs_plane;
1642
1643         for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
1644                 int main_hsub, main_vsub;
1645                 int hsub, vsub;
1646                 int x, y;
1647
1648                 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane))
1649                         continue;
1650
1651                 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
1652                                                skl_ccs_to_main_plane(fb, ccs_plane));
1653                 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1654
1655                 hsub *= main_hsub;
1656                 vsub *= main_vsub;
1657                 x = src_x / hsub;
1658                 y = src_y / vsub;
1659
1660                 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
1661
1662                 offset = intel_plane_compute_aligned_offset(&x, &y,
1663                                                             plane_state,
1664                                                             ccs_plane);
1665
1666                 plane_state->view.color_plane[ccs_plane].offset = offset;
1667                 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
1668                 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
1669         }
1670
1671         return 0;
1672 }
1673
1674 static int skl_check_plane_surface(struct intel_plane_state *plane_state)
1675 {
1676         const struct drm_framebuffer *fb = plane_state->hw.fb;
1677         int ret;
1678
1679         ret = intel_plane_compute_gtt(plane_state);
1680         if (ret)
1681                 return ret;
1682
1683         if (!plane_state->uapi.visible)
1684                 return 0;
1685
1686         /*
1687          * Handle the AUX surface first since the main surface setup depends on
1688          * it.
1689          */
1690         if (intel_fb_is_ccs_modifier(fb->modifier)) {
1691                 ret = skl_check_ccs_aux_surface(plane_state);
1692                 if (ret)
1693                         return ret;
1694         }
1695
1696         if (intel_format_info_is_yuv_semiplanar(fb->format,
1697                                                 fb->modifier)) {
1698                 ret = skl_check_nv12_aux_surface(plane_state);
1699                 if (ret)
1700                         return ret;
1701         }
1702
1703         ret = skl_check_main_surface(plane_state);
1704         if (ret)
1705                 return ret;
1706
1707         return 0;
1708 }
1709
1710 static bool skl_fb_scalable(const struct drm_framebuffer *fb)
1711 {
1712         if (!fb)
1713                 return false;
1714
1715         switch (fb->format->format) {
1716         case DRM_FORMAT_C8:
1717                 return false;
1718         case DRM_FORMAT_XRGB16161616F:
1719         case DRM_FORMAT_ARGB16161616F:
1720         case DRM_FORMAT_XBGR16161616F:
1721         case DRM_FORMAT_ABGR16161616F:
1722                 return DISPLAY_VER(to_i915(fb->dev)) >= 11;
1723         default:
1724                 return true;
1725         }
1726 }
1727
1728 static bool bo_has_valid_encryption(struct drm_i915_gem_object *obj)
1729 {
1730         struct drm_i915_private *i915 = to_i915(obj->base.dev);
1731
1732         return intel_pxp_key_check(&i915->gt.pxp, obj, false) == 0;
1733 }
1734
1735 static bool pxp_is_borked(struct drm_i915_gem_object *obj)
1736 {
1737         return i915_gem_object_is_protected(obj) && !bo_has_valid_encryption(obj);
1738 }
1739
1740 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1741                            struct intel_plane_state *plane_state)
1742 {
1743         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1744         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1745         const struct drm_framebuffer *fb = plane_state->hw.fb;
1746         int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1747         int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1748         int ret;
1749
1750         ret = skl_plane_check_fb(crtc_state, plane_state);
1751         if (ret)
1752                 return ret;
1753
1754         /* use scaler when colorkey is not required */
1755         if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
1756                 min_scale = 1;
1757                 max_scale = skl_plane_max_scale(dev_priv, fb);
1758         }
1759
1760         ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1761                                                 min_scale, max_scale, true);
1762         if (ret)
1763                 return ret;
1764
1765         ret = skl_check_plane_surface(plane_state);
1766         if (ret)
1767                 return ret;
1768
1769         if (!plane_state->uapi.visible)
1770                 return 0;
1771
1772         ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1773         if (ret)
1774                 return ret;
1775
1776         ret = intel_plane_check_src_coordinates(plane_state);
1777         if (ret)
1778                 return ret;
1779
1780         ret = skl_plane_check_nv12_rotation(plane_state);
1781         if (ret)
1782                 return ret;
1783
1784         if (DISPLAY_VER(dev_priv) >= 11) {
1785                 plane_state->decrypt = bo_has_valid_encryption(intel_fb_obj(fb));
1786                 plane_state->force_black = pxp_is_borked(intel_fb_obj(fb));
1787         }
1788
1789         /* HW only has 8 bits pixel precision, disable plane if invisible */
1790         if (!(plane_state->hw.alpha >> 8))
1791                 plane_state->uapi.visible = false;
1792
1793         plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1794
1795         if (DISPLAY_VER(dev_priv) >= 10)
1796                 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1797                                                              plane_state);
1798
1799         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1800             icl_is_hdr_plane(dev_priv, plane->id))
1801                 /* Enable and use MPEG-2 chroma siting */
1802                 plane_state->cus_ctl = PLANE_CUS_ENABLE |
1803                         PLANE_CUS_HPHASE_0 |
1804                         PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
1805         else
1806                 plane_state->cus_ctl = 0;
1807
1808         return 0;
1809 }
1810
1811 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
1812                               enum pipe pipe, enum plane_id plane_id)
1813 {
1814         if (!HAS_FBC(dev_priv))
1815                 return false;
1816
1817         return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
1818 }
1819
1820 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
1821                                  enum pipe pipe, enum plane_id plane_id)
1822 {
1823         /* Display WA #0870: skl, bxt */
1824         if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
1825                 return false;
1826
1827         if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
1828                 return false;
1829
1830         if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
1831                 return false;
1832
1833         return true;
1834 }
1835
1836 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
1837                                         enum pipe pipe, enum plane_id plane_id,
1838                                         int *num_formats)
1839 {
1840         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1841                 *num_formats = ARRAY_SIZE(skl_planar_formats);
1842                 return skl_planar_formats;
1843         } else {
1844                 *num_formats = ARRAY_SIZE(skl_plane_formats);
1845                 return skl_plane_formats;
1846         }
1847 }
1848
1849 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
1850                                         enum pipe pipe, enum plane_id plane_id,
1851                                         int *num_formats)
1852 {
1853         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1854                 *num_formats = ARRAY_SIZE(glk_planar_formats);
1855                 return glk_planar_formats;
1856         } else {
1857                 *num_formats = ARRAY_SIZE(skl_plane_formats);
1858                 return skl_plane_formats;
1859         }
1860 }
1861
1862 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
1863                                         enum pipe pipe, enum plane_id plane_id,
1864                                         int *num_formats)
1865 {
1866         if (icl_is_hdr_plane(dev_priv, plane_id)) {
1867                 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
1868                 return icl_hdr_plane_formats;
1869         } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
1870                 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
1871                 return icl_sdr_y_plane_formats;
1872         } else {
1873                 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
1874                 return icl_sdr_uv_plane_formats;
1875         }
1876 }
1877
1878 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1879                                            u32 format, u64 modifier)
1880 {
1881         struct intel_plane *plane = to_intel_plane(_plane);
1882
1883         if (!intel_fb_plane_supports_modifier(plane, modifier))
1884                 return false;
1885
1886         switch (format) {
1887         case DRM_FORMAT_XRGB8888:
1888         case DRM_FORMAT_XBGR8888:
1889         case DRM_FORMAT_ARGB8888:
1890         case DRM_FORMAT_ABGR8888:
1891                 if (intel_fb_is_ccs_modifier(modifier))
1892                         return true;
1893                 fallthrough;
1894         case DRM_FORMAT_RGB565:
1895         case DRM_FORMAT_XRGB2101010:
1896         case DRM_FORMAT_XBGR2101010:
1897         case DRM_FORMAT_ARGB2101010:
1898         case DRM_FORMAT_ABGR2101010:
1899         case DRM_FORMAT_YUYV:
1900         case DRM_FORMAT_YVYU:
1901         case DRM_FORMAT_UYVY:
1902         case DRM_FORMAT_VYUY:
1903         case DRM_FORMAT_NV12:
1904         case DRM_FORMAT_XYUV8888:
1905         case DRM_FORMAT_P010:
1906         case DRM_FORMAT_P012:
1907         case DRM_FORMAT_P016:
1908         case DRM_FORMAT_XVYU2101010:
1909                 if (modifier == I915_FORMAT_MOD_Yf_TILED)
1910                         return true;
1911                 fallthrough;
1912         case DRM_FORMAT_C8:
1913         case DRM_FORMAT_XBGR16161616F:
1914         case DRM_FORMAT_ABGR16161616F:
1915         case DRM_FORMAT_XRGB16161616F:
1916         case DRM_FORMAT_ARGB16161616F:
1917         case DRM_FORMAT_Y210:
1918         case DRM_FORMAT_Y212:
1919         case DRM_FORMAT_Y216:
1920         case DRM_FORMAT_XVYU12_16161616:
1921         case DRM_FORMAT_XVYU16161616:
1922                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1923                     modifier == I915_FORMAT_MOD_X_TILED ||
1924                     modifier == I915_FORMAT_MOD_Y_TILED)
1925                         return true;
1926                 fallthrough;
1927         default:
1928                 return false;
1929         }
1930 }
1931
1932 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
1933                                              u32 format, u64 modifier)
1934 {
1935         struct intel_plane *plane = to_intel_plane(_plane);
1936
1937         if (!intel_fb_plane_supports_modifier(plane, modifier))
1938                 return false;
1939
1940         switch (format) {
1941         case DRM_FORMAT_XRGB8888:
1942         case DRM_FORMAT_XBGR8888:
1943         case DRM_FORMAT_ARGB8888:
1944         case DRM_FORMAT_ABGR8888:
1945                 if (intel_fb_is_ccs_modifier(modifier))
1946                         return true;
1947                 fallthrough;
1948         case DRM_FORMAT_YUYV:
1949         case DRM_FORMAT_YVYU:
1950         case DRM_FORMAT_UYVY:
1951         case DRM_FORMAT_VYUY:
1952         case DRM_FORMAT_NV12:
1953         case DRM_FORMAT_XYUV8888:
1954         case DRM_FORMAT_P010:
1955         case DRM_FORMAT_P012:
1956         case DRM_FORMAT_P016:
1957                 if (intel_fb_is_mc_ccs_modifier(modifier))
1958                         return true;
1959                 fallthrough;
1960         case DRM_FORMAT_RGB565:
1961         case DRM_FORMAT_XRGB2101010:
1962         case DRM_FORMAT_XBGR2101010:
1963         case DRM_FORMAT_ARGB2101010:
1964         case DRM_FORMAT_ABGR2101010:
1965         case DRM_FORMAT_XVYU2101010:
1966         case DRM_FORMAT_C8:
1967         case DRM_FORMAT_XBGR16161616F:
1968         case DRM_FORMAT_ABGR16161616F:
1969         case DRM_FORMAT_XRGB16161616F:
1970         case DRM_FORMAT_ARGB16161616F:
1971         case DRM_FORMAT_Y210:
1972         case DRM_FORMAT_Y212:
1973         case DRM_FORMAT_Y216:
1974         case DRM_FORMAT_XVYU12_16161616:
1975         case DRM_FORMAT_XVYU16161616:
1976                 if (!intel_fb_is_ccs_modifier(modifier))
1977                         return true;
1978                 fallthrough;
1979         default:
1980                 return false;
1981         }
1982 }
1983
1984 static const struct drm_plane_funcs skl_plane_funcs = {
1985         .update_plane = drm_atomic_helper_update_plane,
1986         .disable_plane = drm_atomic_helper_disable_plane,
1987         .destroy = intel_plane_destroy,
1988         .atomic_duplicate_state = intel_plane_duplicate_state,
1989         .atomic_destroy_state = intel_plane_destroy_state,
1990         .format_mod_supported = skl_plane_format_mod_supported,
1991 };
1992
1993 static const struct drm_plane_funcs gen12_plane_funcs = {
1994         .update_plane = drm_atomic_helper_update_plane,
1995         .disable_plane = drm_atomic_helper_disable_plane,
1996         .destroy = intel_plane_destroy,
1997         .atomic_duplicate_state = intel_plane_duplicate_state,
1998         .atomic_destroy_state = intel_plane_destroy_state,
1999         .format_mod_supported = gen12_plane_format_mod_supported,
2000 };
2001
2002 static void
2003 skl_plane_enable_flip_done(struct intel_plane *plane)
2004 {
2005         struct drm_i915_private *i915 = to_i915(plane->base.dev);
2006         enum pipe pipe = plane->pipe;
2007
2008         spin_lock_irq(&i915->irq_lock);
2009         bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2010         spin_unlock_irq(&i915->irq_lock);
2011 }
2012
2013 static void
2014 skl_plane_disable_flip_done(struct intel_plane *plane)
2015 {
2016         struct drm_i915_private *i915 = to_i915(plane->base.dev);
2017         enum pipe pipe = plane->pipe;
2018
2019         spin_lock_irq(&i915->irq_lock);
2020         bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2021         spin_unlock_irq(&i915->irq_lock);
2022 }
2023
2024 static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915,
2025                                  enum pipe pipe, enum plane_id plane_id)
2026 {
2027         /* Wa_22011186057 */
2028         if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2029                 return false;
2030
2031         if (DISPLAY_VER(i915) >= 11)
2032                 return true;
2033
2034         if (IS_GEMINILAKE(i915))
2035                 return pipe != PIPE_C;
2036
2037         return pipe != PIPE_C &&
2038                 (plane_id == PLANE_PRIMARY ||
2039                  plane_id == PLANE_SPRITE0);
2040 }
2041
2042 static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
2043                                    enum plane_id plane_id)
2044 {
2045         if (DISPLAY_VER(i915) < 12)
2046                 return false;
2047
2048         /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
2049         if (IS_DG1(i915) || IS_ROCKETLAKE(i915) ||
2050             IS_TGL_DISPLAY_STEP(i915, STEP_A0, STEP_D0))
2051                 return false;
2052
2053         /* Wa_22011186057 */
2054         if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2055                 return false;
2056
2057         return plane_id < PLANE_SPRITE4;
2058 }
2059
2060 static u8 skl_get_plane_caps(struct drm_i915_private *i915,
2061                              enum pipe pipe, enum plane_id plane_id)
2062 {
2063         u8 caps = INTEL_PLANE_CAP_TILING_X;
2064
2065         if (DISPLAY_VER(i915) < 13 || IS_ALDERLAKE_P(i915))
2066                 caps |= INTEL_PLANE_CAP_TILING_Y;
2067         if (DISPLAY_VER(i915) < 12)
2068                 caps |= INTEL_PLANE_CAP_TILING_Yf;
2069
2070         if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
2071                 caps |= INTEL_PLANE_CAP_CCS_RC;
2072                 if (DISPLAY_VER(i915) >= 12)
2073                         caps |= INTEL_PLANE_CAP_CCS_RC_CC;
2074         }
2075
2076         if (gen12_plane_has_mc_ccs(i915, plane_id))
2077                 caps |= INTEL_PLANE_CAP_CCS_MC;
2078
2079         return caps;
2080 }
2081
2082 struct intel_plane *
2083 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2084                            enum pipe pipe, enum plane_id plane_id)
2085 {
2086         const struct drm_plane_funcs *plane_funcs;
2087         struct intel_plane *plane;
2088         enum drm_plane_type plane_type;
2089         unsigned int supported_rotations;
2090         unsigned int supported_csc;
2091         const u64 *modifiers;
2092         const u32 *formats;
2093         int num_formats;
2094         int ret;
2095
2096         plane = intel_plane_alloc();
2097         if (IS_ERR(plane))
2098                 return plane;
2099
2100         plane->pipe = pipe;
2101         plane->id = plane_id;
2102         plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2103
2104         if (skl_plane_has_fbc(dev_priv, pipe, plane_id))
2105                 plane->fbc = &dev_priv->fbc;
2106         if (plane->fbc)
2107                 plane->fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2108
2109         if (DISPLAY_VER(dev_priv) >= 11) {
2110                 plane->min_width = icl_plane_min_width;
2111                 plane->max_width = icl_plane_max_width;
2112                 plane->max_height = icl_plane_max_height;
2113                 plane->min_cdclk = icl_plane_min_cdclk;
2114         } else if (DISPLAY_VER(dev_priv) >= 10) {
2115                 plane->max_width = glk_plane_max_width;
2116                 plane->max_height = skl_plane_max_height;
2117                 plane->min_cdclk = glk_plane_min_cdclk;
2118         } else {
2119                 plane->max_width = skl_plane_max_width;
2120                 plane->max_height = skl_plane_max_height;
2121                 plane->min_cdclk = skl_plane_min_cdclk;
2122         }
2123
2124         plane->max_stride = skl_plane_max_stride;
2125         plane->update_noarm = skl_plane_update_noarm;
2126         plane->update_arm = skl_plane_update_arm;
2127         plane->disable_arm = skl_plane_disable_arm;
2128         plane->get_hw_state = skl_plane_get_hw_state;
2129         plane->check_plane = skl_plane_check;
2130
2131         if (plane_id == PLANE_PRIMARY) {
2132                 plane->need_async_flip_disable_wa = IS_DISPLAY_VER(dev_priv,
2133                                                                    9, 10);
2134                 plane->async_flip = skl_plane_async_flip;
2135                 plane->enable_flip_done = skl_plane_enable_flip_done;
2136                 plane->disable_flip_done = skl_plane_disable_flip_done;
2137         }
2138
2139         if (DISPLAY_VER(dev_priv) >= 11)
2140                 formats = icl_get_plane_formats(dev_priv, pipe,
2141                                                 plane_id, &num_formats);
2142         else if (DISPLAY_VER(dev_priv) >= 10)
2143                 formats = glk_get_plane_formats(dev_priv, pipe,
2144                                                 plane_id, &num_formats);
2145         else
2146                 formats = skl_get_plane_formats(dev_priv, pipe,
2147                                                 plane_id, &num_formats);
2148
2149         if (DISPLAY_VER(dev_priv) >= 12)
2150                 plane_funcs = &gen12_plane_funcs;
2151         else
2152                 plane_funcs = &skl_plane_funcs;
2153
2154         if (plane_id == PLANE_PRIMARY)
2155                 plane_type = DRM_PLANE_TYPE_PRIMARY;
2156         else
2157                 plane_type = DRM_PLANE_TYPE_OVERLAY;
2158
2159         modifiers = intel_fb_plane_get_modifiers(dev_priv,
2160                                                  skl_get_plane_caps(dev_priv, pipe, plane_id));
2161
2162         ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2163                                        0, plane_funcs,
2164                                        formats, num_formats, modifiers,
2165                                        plane_type,
2166                                        "plane %d%c", plane_id + 1,
2167                                        pipe_name(pipe));
2168
2169         kfree(modifiers);
2170
2171         if (ret)
2172                 goto fail;
2173
2174         if (DISPLAY_VER(dev_priv) >= 13)
2175                 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2176         else
2177                 supported_rotations =
2178                         DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2179                         DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2180
2181         if (DISPLAY_VER(dev_priv) >= 11)
2182                 supported_rotations |= DRM_MODE_REFLECT_X;
2183
2184         drm_plane_create_rotation_property(&plane->base,
2185                                            DRM_MODE_ROTATE_0,
2186                                            supported_rotations);
2187
2188         supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2189
2190         if (DISPLAY_VER(dev_priv) >= 10)
2191                 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2192
2193         drm_plane_create_color_properties(&plane->base,
2194                                           supported_csc,
2195                                           BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2196                                           BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2197                                           DRM_COLOR_YCBCR_BT709,
2198                                           DRM_COLOR_YCBCR_LIMITED_RANGE);
2199
2200         drm_plane_create_alpha_property(&plane->base);
2201         drm_plane_create_blend_mode_property(&plane->base,
2202                                              BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2203                                              BIT(DRM_MODE_BLEND_PREMULTI) |
2204                                              BIT(DRM_MODE_BLEND_COVERAGE));
2205
2206         drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2207
2208         if (DISPLAY_VER(dev_priv) >= 12)
2209                 drm_plane_enable_fb_damage_clips(&plane->base);
2210
2211         if (DISPLAY_VER(dev_priv) >= 11)
2212                 drm_plane_create_scaling_filter_property(&plane->base,
2213                                                 BIT(DRM_SCALING_FILTER_DEFAULT) |
2214                                                 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2215
2216         intel_plane_helper_add(plane);
2217
2218         return plane;
2219
2220 fail:
2221         intel_plane_free(plane);
2222
2223         return ERR_PTR(ret);
2224 }
2225
2226 void
2227 skl_get_initial_plane_config(struct intel_crtc *crtc,
2228                              struct intel_initial_plane_config *plane_config)
2229 {
2230         struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2231         struct drm_device *dev = crtc->base.dev;
2232         struct drm_i915_private *dev_priv = to_i915(dev);
2233         struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2234         enum plane_id plane_id = plane->id;
2235         enum pipe pipe;
2236         u32 val, base, offset, stride_mult, tiling, alpha;
2237         int fourcc, pixel_format;
2238         unsigned int aligned_height;
2239         struct drm_framebuffer *fb;
2240         struct intel_framebuffer *intel_fb;
2241
2242         if (!plane->get_hw_state(plane, &pipe))
2243                 return;
2244
2245         drm_WARN_ON(dev, pipe != crtc->pipe);
2246
2247         if (crtc_state->bigjoiner) {
2248                 drm_dbg_kms(&dev_priv->drm,
2249                             "Unsupported bigjoiner configuration for initial FB\n");
2250                 return;
2251         }
2252
2253         intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2254         if (!intel_fb) {
2255                 drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2256                 return;
2257         }
2258
2259         fb = &intel_fb->base;
2260
2261         fb->dev = dev;
2262
2263         val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2264
2265         if (DISPLAY_VER(dev_priv) >= 11)
2266                 pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
2267         else
2268                 pixel_format = val & PLANE_CTL_FORMAT_MASK;
2269
2270         if (DISPLAY_VER(dev_priv) >= 10) {
2271                 alpha = intel_de_read(dev_priv,
2272                                       PLANE_COLOR_CTL(pipe, plane_id));
2273                 alpha &= PLANE_COLOR_ALPHA_MASK;
2274         } else {
2275                 alpha = val & PLANE_CTL_ALPHA_MASK;
2276         }
2277
2278         fourcc = skl_format_to_fourcc(pixel_format,
2279                                       val & PLANE_CTL_ORDER_RGBX, alpha);
2280         fb->format = drm_format_info(fourcc);
2281
2282         tiling = val & PLANE_CTL_TILED_MASK;
2283         switch (tiling) {
2284         case PLANE_CTL_TILED_LINEAR:
2285                 fb->modifier = DRM_FORMAT_MOD_LINEAR;
2286                 break;
2287         case PLANE_CTL_TILED_X:
2288                 plane_config->tiling = I915_TILING_X;
2289                 fb->modifier = I915_FORMAT_MOD_X_TILED;
2290                 break;
2291         case PLANE_CTL_TILED_Y:
2292                 plane_config->tiling = I915_TILING_Y;
2293                 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2294                         fb->modifier = DISPLAY_VER(dev_priv) >= 12 ?
2295                                 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
2296                                 I915_FORMAT_MOD_Y_TILED_CCS;
2297                 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2298                         fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2299                 else
2300                         fb->modifier = I915_FORMAT_MOD_Y_TILED;
2301                 break;
2302         case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
2303                 if (HAS_4TILE(dev_priv)) {
2304                         fb->modifier = I915_FORMAT_MOD_4_TILED;
2305                 } else {
2306                         if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2307                                 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2308                         else
2309                                 fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2310                 }
2311                 break;
2312         default:
2313                 MISSING_CASE(tiling);
2314                 goto error;
2315         }
2316
2317         /*
2318          * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2319          * while i915 HW rotation is clockwise, thats why this swapping.
2320          */
2321         switch (val & PLANE_CTL_ROTATE_MASK) {
2322         case PLANE_CTL_ROTATE_0:
2323                 plane_config->rotation = DRM_MODE_ROTATE_0;
2324                 break;
2325         case PLANE_CTL_ROTATE_90:
2326                 plane_config->rotation = DRM_MODE_ROTATE_270;
2327                 break;
2328         case PLANE_CTL_ROTATE_180:
2329                 plane_config->rotation = DRM_MODE_ROTATE_180;
2330                 break;
2331         case PLANE_CTL_ROTATE_270:
2332                 plane_config->rotation = DRM_MODE_ROTATE_90;
2333                 break;
2334         }
2335
2336         if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
2337                 plane_config->rotation |= DRM_MODE_REFLECT_X;
2338
2339         /* 90/270 degree rotation would require extra work */
2340         if (drm_rotation_90_or_270(plane_config->rotation))
2341                 goto error;
2342
2343         base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
2344         plane_config->base = base;
2345
2346         offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2347
2348         val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2349         fb->height = ((val >> 16) & 0xffff) + 1;
2350         fb->width = ((val >> 0) & 0xffff) + 1;
2351
2352         val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2353         stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2354
2355         if (DISPLAY_VER(dev_priv) >= 13)
2356                 fb->pitches[0] = (val & PLANE_STRIDE_MASK_XELPD) * stride_mult;
2357         else
2358                 fb->pitches[0] = (val & PLANE_STRIDE_MASK) * stride_mult;
2359
2360         aligned_height = intel_fb_align_height(fb, 0, fb->height);
2361
2362         plane_config->size = fb->pitches[0] * aligned_height;
2363
2364         drm_dbg_kms(&dev_priv->drm,
2365                     "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2366                     crtc->base.name, plane->base.name, fb->width, fb->height,
2367                     fb->format->cpp[0] * 8, base, fb->pitches[0],
2368                     plane_config->size);
2369
2370         plane_config->fb = intel_fb;
2371         return;
2372
2373 error:
2374         kfree(intel_fb);
2375 }