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