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