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