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