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