0f40f8b07724f137316d8cc58f8b5d7316ab59e5
[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 icl_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 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
854 {
855         const struct drm_framebuffer *fb = plane_state->hw.fb;
856
857         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
858                 switch (fb->format->cpp[0]) {
859                 case 2:
860                         return PLANE_CTL_ARB_SLOTS(1);
861                 default:
862                         return PLANE_CTL_ARB_SLOTS(0);
863                 }
864         } else {
865                 switch (fb->format->cpp[0]) {
866                 case 8:
867                         return PLANE_CTL_ARB_SLOTS(3);
868                 case 4:
869                         return PLANE_CTL_ARB_SLOTS(1);
870                 default:
871                         return PLANE_CTL_ARB_SLOTS(0);
872                 }
873         }
874 }
875
876 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
877 {
878         struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
879         u32 plane_ctl = 0;
880
881         if (DISPLAY_VER(dev_priv) >= 10)
882                 return plane_ctl;
883
884         if (crtc_state->gamma_enable)
885                 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
886
887         if (crtc_state->csc_enable)
888                 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
889
890         return plane_ctl;
891 }
892
893 static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
894                          const struct intel_plane_state *plane_state)
895 {
896         struct drm_i915_private *dev_priv =
897                 to_i915(plane_state->uapi.plane->dev);
898         const struct drm_framebuffer *fb = plane_state->hw.fb;
899         unsigned int rotation = plane_state->hw.rotation;
900         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
901         u32 plane_ctl;
902
903         plane_ctl = PLANE_CTL_ENABLE;
904
905         if (DISPLAY_VER(dev_priv) < 10) {
906                 plane_ctl |= skl_plane_ctl_alpha(plane_state);
907                 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
908
909                 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
910                         plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
911
912                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
913                         plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
914         }
915
916         plane_ctl |= skl_plane_ctl_format(fb->format->format);
917         plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
918         plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
919
920         if (DISPLAY_VER(dev_priv) >= 11)
921                 plane_ctl |= icl_plane_ctl_flip(rotation &
922                                                 DRM_MODE_REFLECT_MASK);
923
924         if (key->flags & I915_SET_COLORKEY_DESTINATION)
925                 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
926         else if (key->flags & I915_SET_COLORKEY_SOURCE)
927                 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
928
929         /* Wa_22012358565:adl-p */
930         if (DISPLAY_VER(dev_priv) == 13)
931                 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
932
933         return plane_ctl;
934 }
935
936 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
937 {
938         struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
939         u32 plane_color_ctl = 0;
940
941         if (DISPLAY_VER(dev_priv) >= 11)
942                 return plane_color_ctl;
943
944         if (crtc_state->gamma_enable)
945                 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
946
947         if (crtc_state->csc_enable)
948                 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
949
950         return plane_color_ctl;
951 }
952
953 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
954                                const struct intel_plane_state *plane_state)
955 {
956         struct drm_i915_private *dev_priv =
957                 to_i915(plane_state->uapi.plane->dev);
958         const struct drm_framebuffer *fb = plane_state->hw.fb;
959         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
960         u32 plane_color_ctl = 0;
961
962         plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
963         plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
964
965         if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
966                 switch (plane_state->hw.color_encoding) {
967                 case DRM_COLOR_YCBCR_BT709:
968                         plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
969                         break;
970                 case DRM_COLOR_YCBCR_BT2020:
971                         plane_color_ctl |=
972                                 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
973                         break;
974                 default:
975                         plane_color_ctl |=
976                                 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
977                 }
978                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
979                         plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
980         } else if (fb->format->is_yuv) {
981                 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
982                 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
983                         plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
984         }
985
986         return plane_color_ctl;
987 }
988
989 static u32 skl_surf_address(const struct intel_plane_state *plane_state,
990                             int color_plane)
991 {
992         const struct drm_framebuffer *fb = plane_state->hw.fb;
993         u32 offset = plane_state->view.color_plane[color_plane].offset;
994
995         if (intel_fb_uses_dpt(fb)) {
996                 WARN_ON(offset & 0x1fffff);
997                 return offset >> 9;
998         } else {
999                 WARN_ON(offset & 0xfff);
1000                 return offset;
1001         }
1002 }
1003
1004 static void
1005 skl_program_plane(struct intel_plane *plane,
1006                   const struct intel_crtc_state *crtc_state,
1007                   const struct intel_plane_state *plane_state,
1008                   int color_plane)
1009 {
1010         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1011         enum plane_id plane_id = plane->id;
1012         enum pipe pipe = plane->pipe;
1013         const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1014         u32 surf_addr = skl_surf_address(plane_state, color_plane);
1015         u32 stride = skl_plane_stride(plane_state, color_plane);
1016         const struct drm_framebuffer *fb = plane_state->hw.fb;
1017         int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1018         int crtc_x = plane_state->uapi.dst.x1;
1019         int crtc_y = plane_state->uapi.dst.y1;
1020         u32 x = plane_state->view.color_plane[color_plane].x;
1021         u32 y = plane_state->view.color_plane[color_plane].y;
1022         u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1023         u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1024         u8 alpha = plane_state->hw.alpha >> 8;
1025         u32 plane_color_ctl = 0, aux_dist = 0;
1026         unsigned long irqflags;
1027         u32 keymsk, keymax;
1028         u32 plane_ctl = plane_state->ctl;
1029
1030         plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1031
1032         if (DISPLAY_VER(dev_priv) >= 10)
1033                 plane_color_ctl = plane_state->color_ctl |
1034                         glk_plane_color_ctl_crtc(crtc_state);
1035
1036         /* Sizes are 0 based */
1037         src_w--;
1038         src_h--;
1039
1040         keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
1041
1042         keymsk = key->channel_mask & 0x7ffffff;
1043         if (alpha < 0xff)
1044                 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
1045
1046         /* The scaler will handle the output position */
1047         if (plane_state->scaler_id >= 0) {
1048                 crtc_x = 0;
1049                 crtc_y = 0;
1050         }
1051
1052         if (aux_plane) {
1053                 aux_dist = skl_surf_address(plane_state, aux_plane) - surf_addr;
1054
1055                 if (DISPLAY_VER(dev_priv) < 12)
1056                         aux_dist |= skl_plane_stride(plane_state, aux_plane);
1057         }
1058
1059         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1060
1061         intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
1062         intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
1063                           (crtc_y << 16) | crtc_x);
1064         intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
1065                           (src_h << 16) | src_w);
1066
1067         intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
1068
1069         if (icl_is_hdr_plane(dev_priv, plane_id))
1070                 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
1071                                   plane_state->cus_ctl);
1072
1073         if (DISPLAY_VER(dev_priv) >= 10)
1074                 intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
1075                                   plane_color_ctl);
1076
1077         if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1078                 icl_program_input_csc(plane, crtc_state, plane_state);
1079
1080         if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)
1081                 intel_uncore_write64_fw(&dev_priv->uncore,
1082                                         PLANE_CC_VAL(pipe, plane_id), plane_state->ccval);
1083
1084         skl_write_plane_wm(plane, crtc_state);
1085
1086         intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
1087                           key->min_value);
1088         intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
1089         intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
1090
1091         intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1092                           (y << 16) | x);
1093
1094         if (DISPLAY_VER(dev_priv) < 11)
1095                 intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
1096                                   (plane_state->view.color_plane[1].y << 16) |
1097                                    plane_state->view.color_plane[1].x);
1098
1099         if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
1100                 intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
1101
1102         /*
1103          * Enable the scaler before the plane so that we don't
1104          * get a catastrophic underrun even if the two operations
1105          * end up happening in two different frames.
1106          */
1107         if (plane_state->scaler_id >= 0)
1108                 skl_program_plane_scaler(plane, crtc_state, plane_state);
1109
1110         /*
1111          * The control register self-arms if the plane was previously
1112          * disabled. Try to make the plane enable atomic by writing
1113          * the control register just before the surface register.
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_plane_async_flip(struct intel_plane *plane,
1124                      const struct intel_crtc_state *crtc_state,
1125                      const struct intel_plane_state *plane_state,
1126                      bool async_flip)
1127 {
1128         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1129         unsigned long irqflags;
1130         enum plane_id plane_id = plane->id;
1131         enum pipe pipe = plane->pipe;
1132         u32 surf_addr = plane_state->view.color_plane[0].offset;
1133         u32 plane_ctl = plane_state->ctl;
1134
1135         plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1136
1137         if (async_flip)
1138                 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1139
1140         spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1141
1142         intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1143         intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1144                           intel_plane_ggtt_offset(plane_state) + surf_addr);
1145
1146         spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1147 }
1148
1149 static void
1150 skl_update_plane(struct intel_plane *plane,
1151                  const struct intel_crtc_state *crtc_state,
1152                  const struct intel_plane_state *plane_state)
1153 {
1154         int color_plane = 0;
1155
1156         if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1157                 /* Program the UV plane on planar master */
1158                 color_plane = 1;
1159
1160         skl_program_plane(plane, crtc_state, plane_state, color_plane);
1161 }
1162
1163 static bool intel_format_is_p01x(u32 format)
1164 {
1165         switch (format) {
1166         case DRM_FORMAT_P010:
1167         case DRM_FORMAT_P012:
1168         case DRM_FORMAT_P016:
1169                 return true;
1170         default:
1171                 return false;
1172         }
1173 }
1174
1175 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1176                               const struct intel_plane_state *plane_state)
1177 {
1178         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1179         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1180         const struct drm_framebuffer *fb = plane_state->hw.fb;
1181         unsigned int rotation = plane_state->hw.rotation;
1182
1183         if (!fb)
1184                 return 0;
1185
1186         if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1187             is_ccs_modifier(fb->modifier)) {
1188                 drm_dbg_kms(&dev_priv->drm,
1189                             "RC support only with 0/180 degree rotation (%x)\n",
1190                             rotation);
1191                 return -EINVAL;
1192         }
1193
1194         if (rotation & DRM_MODE_REFLECT_X &&
1195             fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1196                 drm_dbg_kms(&dev_priv->drm,
1197                             "horizontal flip is not supported with linear surface formats\n");
1198                 return -EINVAL;
1199         }
1200
1201         if (drm_rotation_90_or_270(rotation)) {
1202                 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
1203                         drm_dbg_kms(&dev_priv->drm,
1204                                     "Y/Yf tiling required for 90/270!\n");
1205                         return -EINVAL;
1206                 }
1207
1208                 /*
1209                  * 90/270 is not allowed with RGB64 16:16:16:16 and
1210                  * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1211                  */
1212                 switch (fb->format->format) {
1213                 case DRM_FORMAT_RGB565:
1214                         if (DISPLAY_VER(dev_priv) >= 11)
1215                                 break;
1216                         fallthrough;
1217                 case DRM_FORMAT_C8:
1218                 case DRM_FORMAT_XRGB16161616F:
1219                 case DRM_FORMAT_XBGR16161616F:
1220                 case DRM_FORMAT_ARGB16161616F:
1221                 case DRM_FORMAT_ABGR16161616F:
1222                 case DRM_FORMAT_Y210:
1223                 case DRM_FORMAT_Y212:
1224                 case DRM_FORMAT_Y216:
1225                 case DRM_FORMAT_XVYU12_16161616:
1226                 case DRM_FORMAT_XVYU16161616:
1227                         drm_dbg_kms(&dev_priv->drm,
1228                                     "Unsupported pixel format %p4cc for 90/270!\n",
1229                                     &fb->format->format);
1230                         return -EINVAL;
1231                 default:
1232                         break;
1233                 }
1234         }
1235
1236         /* Y-tiling is not supported in IF-ID Interlace mode */
1237         if (crtc_state->hw.enable &&
1238             crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1239             (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1240              fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1241              fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1242              fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
1243              fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
1244              fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
1245              fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) {
1246                 drm_dbg_kms(&dev_priv->drm,
1247                             "Y/Yf tiling not supported in IF-ID mode\n");
1248                 return -EINVAL;
1249         }
1250
1251         /* Wa_1606054188:tgl,adl-s */
1252         if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1253             plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1254             intel_format_is_p01x(fb->format->format)) {
1255                 drm_dbg_kms(&dev_priv->drm,
1256                             "Source color keying not supported with P01x formats\n");
1257                 return -EINVAL;
1258         }
1259
1260         return 0;
1261 }
1262
1263 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1264                                            const struct intel_plane_state *plane_state)
1265 {
1266         struct drm_i915_private *dev_priv =
1267                 to_i915(plane_state->uapi.plane->dev);
1268         int crtc_x = plane_state->uapi.dst.x1;
1269         int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1270         int pipe_src_w = crtc_state->pipe_src_w;
1271
1272         /*
1273          * Display WA #1175: cnl,glk
1274          * Planes other than the cursor may cause FIFO underflow and display
1275          * corruption if starting less than 4 pixels from the right edge of
1276          * the screen.
1277          * Besides the above WA fix the similar problem, where planes other
1278          * than the cursor ending less than 4 pixels from the left edge of the
1279          * screen may cause FIFO underflow and display corruption.
1280          */
1281         if (DISPLAY_VER(dev_priv) == 10 &&
1282             (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1283                 drm_dbg_kms(&dev_priv->drm,
1284                             "requested plane X %s position %d invalid (valid range %d-%d)\n",
1285                             crtc_x + crtc_w < 4 ? "end" : "start",
1286                             crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1287                             4, pipe_src_w - 4);
1288                 return -ERANGE;
1289         }
1290
1291         return 0;
1292 }
1293
1294 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1295 {
1296         const struct drm_framebuffer *fb = plane_state->hw.fb;
1297         unsigned int rotation = plane_state->hw.rotation;
1298         int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1299
1300         /* Display WA #1106 */
1301         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1302             src_w & 3 &&
1303             (rotation == DRM_MODE_ROTATE_270 ||
1304              rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1305                 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1306                 return -EINVAL;
1307         }
1308
1309         return 0;
1310 }
1311
1312 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1313                                const struct drm_framebuffer *fb)
1314 {
1315         /*
1316          * We don't yet know the final source width nor
1317          * whether we can use the HQ scaler mode. Assume
1318          * the best case.
1319          * FIXME need to properly check this later.
1320          */
1321         if (DISPLAY_VER(dev_priv) >= 10 ||
1322             !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1323                 return 0x30000 - 1;
1324         else
1325                 return 0x20000 - 1;
1326 }
1327
1328 static int intel_plane_min_width(struct intel_plane *plane,
1329                                  const struct drm_framebuffer *fb,
1330                                  int color_plane,
1331                                  unsigned int rotation)
1332 {
1333         if (plane->min_width)
1334                 return plane->min_width(fb, color_plane, rotation);
1335         else
1336                 return 1;
1337 }
1338
1339 static int intel_plane_max_width(struct intel_plane *plane,
1340                                  const struct drm_framebuffer *fb,
1341                                  int color_plane,
1342                                  unsigned int rotation)
1343 {
1344         if (plane->max_width)
1345                 return plane->max_width(fb, color_plane, rotation);
1346         else
1347                 return INT_MAX;
1348 }
1349
1350 static int intel_plane_max_height(struct intel_plane *plane,
1351                                   const struct drm_framebuffer *fb,
1352                                   int color_plane,
1353                                   unsigned int rotation)
1354 {
1355         if (plane->max_height)
1356                 return plane->max_height(fb, color_plane, rotation);
1357         else
1358                 return INT_MAX;
1359 }
1360
1361 static bool
1362 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1363                                int main_x, int main_y, u32 main_offset,
1364                                int ccs_plane)
1365 {
1366         const struct drm_framebuffer *fb = plane_state->hw.fb;
1367         int aux_x = plane_state->view.color_plane[ccs_plane].x;
1368         int aux_y = plane_state->view.color_plane[ccs_plane].y;
1369         u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1370         u32 alignment = intel_surf_alignment(fb, ccs_plane);
1371         int hsub;
1372         int vsub;
1373
1374         intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1375         while (aux_offset >= main_offset && aux_y <= main_y) {
1376                 int x, y;
1377
1378                 if (aux_x == main_x && aux_y == main_y)
1379                         break;
1380
1381                 if (aux_offset == 0)
1382                         break;
1383
1384                 x = aux_x / hsub;
1385                 y = aux_y / vsub;
1386                 aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1387                                                                plane_state,
1388                                                                ccs_plane,
1389                                                                aux_offset,
1390                                                                aux_offset -
1391                                                                 alignment);
1392                 aux_x = x * hsub + aux_x % hsub;
1393                 aux_y = y * vsub + aux_y % vsub;
1394         }
1395
1396         if (aux_x != main_x || aux_y != main_y)
1397                 return false;
1398
1399         plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1400         plane_state->view.color_plane[ccs_plane].x = aux_x;
1401         plane_state->view.color_plane[ccs_plane].y = aux_y;
1402
1403         return true;
1404 }
1405
1406
1407 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1408                                  int *x, int *y, u32 *offset)
1409 {
1410         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1411         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1412         const struct drm_framebuffer *fb = plane_state->hw.fb;
1413         const int aux_plane = skl_main_to_aux_plane(fb, 0);
1414         const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1415         const u32 alignment = intel_surf_alignment(fb, 0);
1416         const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1417
1418         intel_add_fb_offsets(x, y, plane_state, 0);
1419         *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1420         if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1421                 return -EINVAL;
1422
1423         /*
1424          * AUX surface offset is specified as the distance from the
1425          * main surface offset, and it must be non-negative. Make
1426          * sure that is what we will get.
1427          */
1428         if (aux_plane && *offset > aux_offset)
1429                 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1430                                                             *offset,
1431                                                             aux_offset & ~(alignment - 1));
1432
1433         /*
1434          * When using an X-tiled surface, the plane blows up
1435          * if the x offset + width exceed the stride.
1436          *
1437          * TODO: linear and Y-tiled seem fine, Yf untested,
1438          */
1439         if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1440                 int cpp = fb->format->cpp[0];
1441
1442                 while ((*x + w) * cpp > plane_state->view.color_plane[0].stride) {
1443                         if (*offset == 0) {
1444                                 drm_dbg_kms(&dev_priv->drm,
1445                                             "Unable to find suitable display surface offset due to X-tiling\n");
1446                                 return -EINVAL;
1447                         }
1448
1449                         *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1450                                                                     *offset,
1451                                                                     *offset - alignment);
1452                 }
1453         }
1454
1455         return 0;
1456 }
1457
1458 static int skl_check_main_surface(struct intel_plane_state *plane_state)
1459 {
1460         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1461         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1462         const struct drm_framebuffer *fb = plane_state->hw.fb;
1463         const unsigned int rotation = plane_state->hw.rotation;
1464         int x = plane_state->uapi.src.x1 >> 16;
1465         int y = plane_state->uapi.src.y1 >> 16;
1466         const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1467         const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1468         const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1469         const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1470         const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1471         const int aux_plane = skl_main_to_aux_plane(fb, 0);
1472         const u32 alignment = intel_surf_alignment(fb, 0);
1473         u32 offset;
1474         int ret;
1475
1476         if (w > max_width || w < min_width || h > max_height) {
1477                 drm_dbg_kms(&dev_priv->drm,
1478                             "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1479                             w, h, min_width, max_width, max_height);
1480                 return -EINVAL;
1481         }
1482
1483         ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1484         if (ret)
1485                 return ret;
1486
1487         /*
1488          * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1489          * they match with the main surface x/y offsets.
1490          */
1491         if (is_ccs_modifier(fb->modifier)) {
1492                 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1493                                                        offset, aux_plane)) {
1494                         if (offset == 0)
1495                                 break;
1496
1497                         offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1498                                                                    offset, offset - alignment);
1499                 }
1500
1501                 if (x != plane_state->view.color_plane[aux_plane].x ||
1502                     y != plane_state->view.color_plane[aux_plane].y) {
1503                         drm_dbg_kms(&dev_priv->drm,
1504                                     "Unable to find suitable display surface offset due to CCS\n");
1505                         return -EINVAL;
1506                 }
1507         }
1508
1509         if (DISPLAY_VER(dev_priv) >= 13)
1510                 drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
1511         else
1512                 drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1513
1514         plane_state->view.color_plane[0].offset = offset;
1515         plane_state->view.color_plane[0].x = x;
1516         plane_state->view.color_plane[0].y = y;
1517
1518         /*
1519          * Put the final coordinates back so that the src
1520          * coordinate checks will see the right values.
1521          */
1522         drm_rect_translate_to(&plane_state->uapi.src,
1523                               x << 16, y << 16);
1524
1525         return 0;
1526 }
1527
1528 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1529 {
1530         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1531         struct drm_i915_private *i915 = to_i915(plane->base.dev);
1532         const struct drm_framebuffer *fb = plane_state->hw.fb;
1533         unsigned int rotation = plane_state->hw.rotation;
1534         int uv_plane = 1;
1535         int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
1536         int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
1537         int x = plane_state->uapi.src.x1 >> 17;
1538         int y = plane_state->uapi.src.y1 >> 17;
1539         int w = drm_rect_width(&plane_state->uapi.src) >> 17;
1540         int h = drm_rect_height(&plane_state->uapi.src) >> 17;
1541         u32 offset;
1542
1543         /* FIXME not quite sure how/if these apply to the chroma plane */
1544         if (w > max_width || h > max_height) {
1545                 drm_dbg_kms(&i915->drm,
1546                             "CbCr source size %dx%d too big (limit %dx%d)\n",
1547                             w, h, max_width, max_height);
1548                 return -EINVAL;
1549         }
1550
1551         intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
1552         offset = intel_plane_compute_aligned_offset(&x, &y,
1553                                                     plane_state, uv_plane);
1554
1555         if (is_ccs_modifier(fb->modifier)) {
1556                 int ccs_plane = main_to_ccs_plane(fb, uv_plane);
1557                 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1558                 u32 alignment = intel_surf_alignment(fb, uv_plane);
1559
1560                 if (offset > aux_offset)
1561                         offset = intel_plane_adjust_aligned_offset(&x, &y,
1562                                                                    plane_state,
1563                                                                    uv_plane,
1564                                                                    offset,
1565                                                                    aux_offset & ~(alignment - 1));
1566
1567                 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1568                                                        offset, ccs_plane)) {
1569                         if (offset == 0)
1570                                 break;
1571
1572                         offset = intel_plane_adjust_aligned_offset(&x, &y,
1573                                                                    plane_state,
1574                                                                    uv_plane,
1575                                                                    offset, offset - alignment);
1576                 }
1577
1578                 if (x != plane_state->view.color_plane[ccs_plane].x ||
1579                     y != plane_state->view.color_plane[ccs_plane].y) {
1580                         drm_dbg_kms(&i915->drm,
1581                                     "Unable to find suitable display surface offset due to CCS\n");
1582                         return -EINVAL;
1583                 }
1584         }
1585
1586         if (DISPLAY_VER(i915) >= 13)
1587                 drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
1588         else
1589                 drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
1590
1591         plane_state->view.color_plane[uv_plane].offset = offset;
1592         plane_state->view.color_plane[uv_plane].x = x;
1593         plane_state->view.color_plane[uv_plane].y = y;
1594
1595         return 0;
1596 }
1597
1598 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
1599 {
1600         const struct drm_framebuffer *fb = plane_state->hw.fb;
1601         int src_x = plane_state->uapi.src.x1 >> 16;
1602         int src_y = plane_state->uapi.src.y1 >> 16;
1603         u32 offset;
1604         int ccs_plane;
1605
1606         for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
1607                 int main_hsub, main_vsub;
1608                 int hsub, vsub;
1609                 int x, y;
1610
1611                 if (!is_ccs_plane(fb, ccs_plane) ||
1612                     is_gen12_ccs_cc_plane(fb, ccs_plane))
1613                         continue;
1614
1615                 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
1616                                                skl_ccs_to_main_plane(fb, ccs_plane));
1617                 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1618
1619                 hsub *= main_hsub;
1620                 vsub *= main_vsub;
1621                 x = src_x / hsub;
1622                 y = src_y / vsub;
1623
1624                 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
1625
1626                 offset = intel_plane_compute_aligned_offset(&x, &y,
1627                                                             plane_state,
1628                                                             ccs_plane);
1629
1630                 plane_state->view.color_plane[ccs_plane].offset = offset;
1631                 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
1632                 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
1633         }
1634
1635         return 0;
1636 }
1637
1638 static int skl_check_plane_surface(struct intel_plane_state *plane_state)
1639 {
1640         const struct drm_framebuffer *fb = plane_state->hw.fb;
1641         int ret;
1642
1643         ret = intel_plane_compute_gtt(plane_state);
1644         if (ret)
1645                 return ret;
1646
1647         if (!plane_state->uapi.visible)
1648                 return 0;
1649
1650         /*
1651          * Handle the AUX surface first since the main surface setup depends on
1652          * it.
1653          */
1654         if (is_ccs_modifier(fb->modifier)) {
1655                 ret = skl_check_ccs_aux_surface(plane_state);
1656                 if (ret)
1657                         return ret;
1658         }
1659
1660         if (intel_format_info_is_yuv_semiplanar(fb->format,
1661                                                 fb->modifier)) {
1662                 ret = skl_check_nv12_aux_surface(plane_state);
1663                 if (ret)
1664                         return ret;
1665         }
1666
1667         ret = skl_check_main_surface(plane_state);
1668         if (ret)
1669                 return ret;
1670
1671         return 0;
1672 }
1673
1674 static bool skl_fb_scalable(const struct drm_framebuffer *fb)
1675 {
1676         if (!fb)
1677                 return false;
1678
1679         switch (fb->format->format) {
1680         case DRM_FORMAT_C8:
1681                 return false;
1682         case DRM_FORMAT_XRGB16161616F:
1683         case DRM_FORMAT_ARGB16161616F:
1684         case DRM_FORMAT_XBGR16161616F:
1685         case DRM_FORMAT_ABGR16161616F:
1686                 return DISPLAY_VER(to_i915(fb->dev)) >= 11;
1687         default:
1688                 return true;
1689         }
1690 }
1691
1692 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1693                            struct intel_plane_state *plane_state)
1694 {
1695         struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1696         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1697         const struct drm_framebuffer *fb = plane_state->hw.fb;
1698         int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1699         int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1700         int ret;
1701
1702         ret = skl_plane_check_fb(crtc_state, plane_state);
1703         if (ret)
1704                 return ret;
1705
1706         /* use scaler when colorkey is not required */
1707         if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
1708                 min_scale = 1;
1709                 max_scale = skl_plane_max_scale(dev_priv, fb);
1710         }
1711
1712         ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1713                                                 min_scale, max_scale, true);
1714         if (ret)
1715                 return ret;
1716
1717         ret = skl_check_plane_surface(plane_state);
1718         if (ret)
1719                 return ret;
1720
1721         if (!plane_state->uapi.visible)
1722                 return 0;
1723
1724         ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1725         if (ret)
1726                 return ret;
1727
1728         ret = intel_plane_check_src_coordinates(plane_state);
1729         if (ret)
1730                 return ret;
1731
1732         ret = skl_plane_check_nv12_rotation(plane_state);
1733         if (ret)
1734                 return ret;
1735
1736         /* HW only has 8 bits pixel precision, disable plane if invisible */
1737         if (!(plane_state->hw.alpha >> 8))
1738                 plane_state->uapi.visible = false;
1739
1740         plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1741
1742         if (DISPLAY_VER(dev_priv) >= 10)
1743                 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1744                                                              plane_state);
1745
1746         if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1747             icl_is_hdr_plane(dev_priv, plane->id))
1748                 /* Enable and use MPEG-2 chroma siting */
1749                 plane_state->cus_ctl = PLANE_CUS_ENABLE |
1750                         PLANE_CUS_HPHASE_0 |
1751                         PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
1752         else
1753                 plane_state->cus_ctl = 0;
1754
1755         return 0;
1756 }
1757
1758 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
1759                               enum pipe pipe, enum plane_id plane_id)
1760 {
1761         if (!HAS_FBC(dev_priv))
1762                 return false;
1763
1764         return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
1765 }
1766
1767 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
1768                                  enum pipe pipe, enum plane_id plane_id)
1769 {
1770         /* Display WA #0870: skl, bxt */
1771         if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
1772                 return false;
1773
1774         if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
1775                 return false;
1776
1777         if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
1778                 return false;
1779
1780         return true;
1781 }
1782
1783 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
1784                                         enum pipe pipe, enum plane_id plane_id,
1785                                         int *num_formats)
1786 {
1787         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1788                 *num_formats = ARRAY_SIZE(skl_planar_formats);
1789                 return skl_planar_formats;
1790         } else {
1791                 *num_formats = ARRAY_SIZE(skl_plane_formats);
1792                 return skl_plane_formats;
1793         }
1794 }
1795
1796 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
1797                                         enum pipe pipe, enum plane_id plane_id,
1798                                         int *num_formats)
1799 {
1800         if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1801                 *num_formats = ARRAY_SIZE(glk_planar_formats);
1802                 return glk_planar_formats;
1803         } else {
1804                 *num_formats = ARRAY_SIZE(skl_plane_formats);
1805                 return skl_plane_formats;
1806         }
1807 }
1808
1809 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
1810                                         enum pipe pipe, enum plane_id plane_id,
1811                                         int *num_formats)
1812 {
1813         if (icl_is_hdr_plane(dev_priv, plane_id)) {
1814                 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
1815                 return icl_hdr_plane_formats;
1816         } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
1817                 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
1818                 return icl_sdr_y_plane_formats;
1819         } else {
1820                 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
1821                 return icl_sdr_uv_plane_formats;
1822         }
1823 }
1824
1825 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1826                               enum pipe pipe, enum plane_id plane_id)
1827 {
1828         if (plane_id == PLANE_CURSOR)
1829                 return false;
1830
1831         if (DISPLAY_VER(dev_priv) >= 11)
1832                 return true;
1833
1834         if (IS_GEMINILAKE(dev_priv))
1835                 return pipe != PIPE_C;
1836
1837         return pipe != PIPE_C &&
1838                 (plane_id == PLANE_PRIMARY ||
1839                  plane_id == PLANE_SPRITE0);
1840 }
1841
1842 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1843                                            u32 format, u64 modifier)
1844 {
1845         struct intel_plane *plane = to_intel_plane(_plane);
1846
1847         switch (modifier) {
1848         case DRM_FORMAT_MOD_LINEAR:
1849         case I915_FORMAT_MOD_X_TILED:
1850         case I915_FORMAT_MOD_Y_TILED:
1851         case I915_FORMAT_MOD_Yf_TILED:
1852                 break;
1853         case I915_FORMAT_MOD_Y_TILED_CCS:
1854         case I915_FORMAT_MOD_Yf_TILED_CCS:
1855                 if (!plane->has_ccs)
1856                         return false;
1857                 break;
1858         default:
1859                 return false;
1860         }
1861
1862         switch (format) {
1863         case DRM_FORMAT_XRGB8888:
1864         case DRM_FORMAT_XBGR8888:
1865         case DRM_FORMAT_ARGB8888:
1866         case DRM_FORMAT_ABGR8888:
1867                 if (is_ccs_modifier(modifier))
1868                         return true;
1869                 fallthrough;
1870         case DRM_FORMAT_RGB565:
1871         case DRM_FORMAT_XRGB2101010:
1872         case DRM_FORMAT_XBGR2101010:
1873         case DRM_FORMAT_ARGB2101010:
1874         case DRM_FORMAT_ABGR2101010:
1875         case DRM_FORMAT_YUYV:
1876         case DRM_FORMAT_YVYU:
1877         case DRM_FORMAT_UYVY:
1878         case DRM_FORMAT_VYUY:
1879         case DRM_FORMAT_NV12:
1880         case DRM_FORMAT_XYUV8888:
1881         case DRM_FORMAT_P010:
1882         case DRM_FORMAT_P012:
1883         case DRM_FORMAT_P016:
1884         case DRM_FORMAT_XVYU2101010:
1885                 if (modifier == I915_FORMAT_MOD_Yf_TILED)
1886                         return true;
1887                 fallthrough;
1888         case DRM_FORMAT_C8:
1889         case DRM_FORMAT_XBGR16161616F:
1890         case DRM_FORMAT_ABGR16161616F:
1891         case DRM_FORMAT_XRGB16161616F:
1892         case DRM_FORMAT_ARGB16161616F:
1893         case DRM_FORMAT_Y210:
1894         case DRM_FORMAT_Y212:
1895         case DRM_FORMAT_Y216:
1896         case DRM_FORMAT_XVYU12_16161616:
1897         case DRM_FORMAT_XVYU16161616:
1898                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1899                     modifier == I915_FORMAT_MOD_X_TILED ||
1900                     modifier == I915_FORMAT_MOD_Y_TILED)
1901                         return true;
1902                 fallthrough;
1903         default:
1904                 return false;
1905         }
1906 }
1907
1908 static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
1909                                         enum plane_id plane_id)
1910 {
1911         /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
1912         if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
1913             IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_D0))
1914                 return false;
1915
1916         /* Wa_22011186057 */
1917         if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
1918                 return false;
1919
1920         return plane_id < PLANE_SPRITE4;
1921 }
1922
1923 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
1924                                              u32 format, u64 modifier)
1925 {
1926         struct drm_i915_private *dev_priv = to_i915(_plane->dev);
1927         struct intel_plane *plane = to_intel_plane(_plane);
1928
1929         switch (modifier) {
1930         case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
1931                 if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
1932                         return false;
1933                 fallthrough;
1934         case DRM_FORMAT_MOD_LINEAR:
1935         case I915_FORMAT_MOD_X_TILED:
1936         case I915_FORMAT_MOD_Y_TILED:
1937                 break;
1938         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
1939         case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
1940                 /* Wa_22011186057 */
1941                 if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
1942                         return false;
1943                 break;
1944         default:
1945                 return false;
1946         }
1947
1948         switch (format) {
1949         case DRM_FORMAT_XRGB8888:
1950         case DRM_FORMAT_XBGR8888:
1951         case DRM_FORMAT_ARGB8888:
1952         case DRM_FORMAT_ABGR8888:
1953                 if (is_ccs_modifier(modifier))
1954                         return true;
1955                 fallthrough;
1956         case DRM_FORMAT_YUYV:
1957         case DRM_FORMAT_YVYU:
1958         case DRM_FORMAT_UYVY:
1959         case DRM_FORMAT_VYUY:
1960         case DRM_FORMAT_NV12:
1961         case DRM_FORMAT_XYUV8888:
1962         case DRM_FORMAT_P010:
1963         case DRM_FORMAT_P012:
1964         case DRM_FORMAT_P016:
1965                 if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
1966                         return true;
1967                 fallthrough;
1968         case DRM_FORMAT_RGB565:
1969         case DRM_FORMAT_XRGB2101010:
1970         case DRM_FORMAT_XBGR2101010:
1971         case DRM_FORMAT_ARGB2101010:
1972         case DRM_FORMAT_ABGR2101010:
1973         case DRM_FORMAT_XVYU2101010:
1974         case DRM_FORMAT_C8:
1975         case DRM_FORMAT_XBGR16161616F:
1976         case DRM_FORMAT_ABGR16161616F:
1977         case DRM_FORMAT_XRGB16161616F:
1978         case DRM_FORMAT_ARGB16161616F:
1979         case DRM_FORMAT_Y210:
1980         case DRM_FORMAT_Y212:
1981         case DRM_FORMAT_Y216:
1982         case DRM_FORMAT_XVYU12_16161616:
1983         case DRM_FORMAT_XVYU16161616:
1984                 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1985                     modifier == I915_FORMAT_MOD_X_TILED ||
1986                     modifier == I915_FORMAT_MOD_Y_TILED)
1987                         return true;
1988                 fallthrough;
1989         default:
1990                 return false;
1991         }
1992 }
1993
1994 static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
1995                                             enum plane_id plane_id)
1996 {
1997         /* Wa_22011186057 */
1998         if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
1999                 return adlp_step_a_plane_format_modifiers;
2000         else if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
2001                 return gen12_plane_format_modifiers_mc_ccs;
2002         else
2003                 return gen12_plane_format_modifiers_rc_ccs;
2004 }
2005
2006 static const struct drm_plane_funcs skl_plane_funcs = {
2007         .update_plane = drm_atomic_helper_update_plane,
2008         .disable_plane = drm_atomic_helper_disable_plane,
2009         .destroy = intel_plane_destroy,
2010         .atomic_duplicate_state = intel_plane_duplicate_state,
2011         .atomic_destroy_state = intel_plane_destroy_state,
2012         .format_mod_supported = skl_plane_format_mod_supported,
2013 };
2014
2015 static const struct drm_plane_funcs gen12_plane_funcs = {
2016         .update_plane = drm_atomic_helper_update_plane,
2017         .disable_plane = drm_atomic_helper_disable_plane,
2018         .destroy = intel_plane_destroy,
2019         .atomic_duplicate_state = intel_plane_duplicate_state,
2020         .atomic_destroy_state = intel_plane_destroy_state,
2021         .format_mod_supported = gen12_plane_format_mod_supported,
2022 };
2023
2024 static void
2025 skl_plane_enable_flip_done(struct intel_plane *plane)
2026 {
2027         struct drm_i915_private *i915 = to_i915(plane->base.dev);
2028         enum pipe pipe = plane->pipe;
2029
2030         spin_lock_irq(&i915->irq_lock);
2031         bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2032         spin_unlock_irq(&i915->irq_lock);
2033 }
2034
2035 static void
2036 skl_plane_disable_flip_done(struct intel_plane *plane)
2037 {
2038         struct drm_i915_private *i915 = to_i915(plane->base.dev);
2039         enum pipe pipe = plane->pipe;
2040
2041         spin_lock_irq(&i915->irq_lock);
2042         bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2043         spin_unlock_irq(&i915->irq_lock);
2044 }
2045
2046 struct intel_plane *
2047 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2048                            enum pipe pipe, enum plane_id plane_id)
2049 {
2050         const struct drm_plane_funcs *plane_funcs;
2051         struct intel_plane *plane;
2052         enum drm_plane_type plane_type;
2053         unsigned int supported_rotations;
2054         unsigned int supported_csc;
2055         const u64 *modifiers;
2056         const u32 *formats;
2057         int num_formats;
2058         int ret;
2059
2060         plane = intel_plane_alloc();
2061         if (IS_ERR(plane))
2062                 return plane;
2063
2064         plane->pipe = pipe;
2065         plane->id = plane_id;
2066         plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2067
2068         plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2069         if (plane->has_fbc) {
2070                 struct intel_fbc *fbc = &dev_priv->fbc;
2071
2072                 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2073         }
2074
2075         if (DISPLAY_VER(dev_priv) >= 11) {
2076                 plane->min_width = icl_plane_min_width;
2077                 plane->max_width = icl_plane_max_width;
2078                 plane->max_height = icl_plane_max_height;
2079                 plane->min_cdclk = icl_plane_min_cdclk;
2080         } else if (DISPLAY_VER(dev_priv) >= 10) {
2081                 plane->max_width = glk_plane_max_width;
2082                 plane->max_height = skl_plane_max_height;
2083                 plane->min_cdclk = glk_plane_min_cdclk;
2084         } else {
2085                 plane->max_width = skl_plane_max_width;
2086                 plane->max_height = skl_plane_max_height;
2087                 plane->min_cdclk = skl_plane_min_cdclk;
2088         }
2089
2090         plane->max_stride = skl_plane_max_stride;
2091         plane->update_plane = skl_update_plane;
2092         plane->disable_plane = skl_disable_plane;
2093         plane->get_hw_state = skl_plane_get_hw_state;
2094         plane->check_plane = skl_plane_check;
2095
2096         if (plane_id == PLANE_PRIMARY) {
2097                 plane->need_async_flip_disable_wa = IS_DISPLAY_VER(dev_priv,
2098                                                                    9, 10);
2099                 plane->async_flip = skl_plane_async_flip;
2100                 plane->enable_flip_done = skl_plane_enable_flip_done;
2101                 plane->disable_flip_done = skl_plane_disable_flip_done;
2102         }
2103
2104         if (DISPLAY_VER(dev_priv) >= 11)
2105                 formats = icl_get_plane_formats(dev_priv, pipe,
2106                                                 plane_id, &num_formats);
2107         else if (DISPLAY_VER(dev_priv) >= 10)
2108                 formats = glk_get_plane_formats(dev_priv, pipe,
2109                                                 plane_id, &num_formats);
2110         else
2111                 formats = skl_get_plane_formats(dev_priv, pipe,
2112                                                 plane_id, &num_formats);
2113
2114         plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2115         if (DISPLAY_VER(dev_priv) >= 12) {
2116                 modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
2117                 plane_funcs = &gen12_plane_funcs;
2118         } else {
2119                 if (plane->has_ccs)
2120                         modifiers = skl_plane_format_modifiers_ccs;
2121                 else
2122                         modifiers = skl_plane_format_modifiers_noccs;
2123                 plane_funcs = &skl_plane_funcs;
2124         }
2125
2126         if (plane_id == PLANE_PRIMARY)
2127                 plane_type = DRM_PLANE_TYPE_PRIMARY;
2128         else
2129                 plane_type = DRM_PLANE_TYPE_OVERLAY;
2130
2131         ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2132                                        0, plane_funcs,
2133                                        formats, num_formats, modifiers,
2134                                        plane_type,
2135                                        "plane %d%c", plane_id + 1,
2136                                        pipe_name(pipe));
2137         if (ret)
2138                 goto fail;
2139
2140         if (DISPLAY_VER(dev_priv) >= 13)
2141                 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2142         else
2143                 supported_rotations =
2144                         DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2145                         DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2146
2147         if (DISPLAY_VER(dev_priv) >= 11)
2148                 supported_rotations |= DRM_MODE_REFLECT_X;
2149
2150         drm_plane_create_rotation_property(&plane->base,
2151                                            DRM_MODE_ROTATE_0,
2152                                            supported_rotations);
2153
2154         supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2155
2156         if (DISPLAY_VER(dev_priv) >= 10)
2157                 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2158
2159         drm_plane_create_color_properties(&plane->base,
2160                                           supported_csc,
2161                                           BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2162                                           BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2163                                           DRM_COLOR_YCBCR_BT709,
2164                                           DRM_COLOR_YCBCR_LIMITED_RANGE);
2165
2166         drm_plane_create_alpha_property(&plane->base);
2167         drm_plane_create_blend_mode_property(&plane->base,
2168                                              BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2169                                              BIT(DRM_MODE_BLEND_PREMULTI) |
2170                                              BIT(DRM_MODE_BLEND_COVERAGE));
2171
2172         drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2173
2174         if (DISPLAY_VER(dev_priv) >= 12)
2175                 drm_plane_enable_fb_damage_clips(&plane->base);
2176
2177         if (DISPLAY_VER(dev_priv) >= 11)
2178                 drm_plane_create_scaling_filter_property(&plane->base,
2179                                                 BIT(DRM_SCALING_FILTER_DEFAULT) |
2180                                                 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2181
2182         intel_plane_helper_add(plane);
2183
2184         return plane;
2185
2186 fail:
2187         intel_plane_free(plane);
2188
2189         return ERR_PTR(ret);
2190 }
2191
2192 void
2193 skl_get_initial_plane_config(struct intel_crtc *crtc,
2194                              struct intel_initial_plane_config *plane_config)
2195 {
2196         struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2197         struct drm_device *dev = crtc->base.dev;
2198         struct drm_i915_private *dev_priv = to_i915(dev);
2199         struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2200         enum plane_id plane_id = plane->id;
2201         enum pipe pipe;
2202         u32 val, base, offset, stride_mult, tiling, alpha;
2203         int fourcc, pixel_format;
2204         unsigned int aligned_height;
2205         struct drm_framebuffer *fb;
2206         struct intel_framebuffer *intel_fb;
2207
2208         if (!plane->get_hw_state(plane, &pipe))
2209                 return;
2210
2211         drm_WARN_ON(dev, pipe != crtc->pipe);
2212
2213         if (crtc_state->bigjoiner) {
2214                 drm_dbg_kms(&dev_priv->drm,
2215                             "Unsupported bigjoiner configuration for initial FB\n");
2216                 return;
2217         }
2218
2219         intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2220         if (!intel_fb) {
2221                 drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2222                 return;
2223         }
2224
2225         fb = &intel_fb->base;
2226
2227         fb->dev = dev;
2228
2229         val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2230
2231         if (DISPLAY_VER(dev_priv) >= 11)
2232                 pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
2233         else
2234                 pixel_format = val & PLANE_CTL_FORMAT_MASK;
2235
2236         if (DISPLAY_VER(dev_priv) >= 10) {
2237                 alpha = intel_de_read(dev_priv,
2238                                       PLANE_COLOR_CTL(pipe, plane_id));
2239                 alpha &= PLANE_COLOR_ALPHA_MASK;
2240         } else {
2241                 alpha = val & PLANE_CTL_ALPHA_MASK;
2242         }
2243
2244         fourcc = skl_format_to_fourcc(pixel_format,
2245                                       val & PLANE_CTL_ORDER_RGBX, alpha);
2246         fb->format = drm_format_info(fourcc);
2247
2248         tiling = val & PLANE_CTL_TILED_MASK;
2249         switch (tiling) {
2250         case PLANE_CTL_TILED_LINEAR:
2251                 fb->modifier = DRM_FORMAT_MOD_LINEAR;
2252                 break;
2253         case PLANE_CTL_TILED_X:
2254                 plane_config->tiling = I915_TILING_X;
2255                 fb->modifier = I915_FORMAT_MOD_X_TILED;
2256                 break;
2257         case PLANE_CTL_TILED_Y:
2258                 plane_config->tiling = I915_TILING_Y;
2259                 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2260                         fb->modifier = DISPLAY_VER(dev_priv) >= 12 ?
2261                                 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
2262                                 I915_FORMAT_MOD_Y_TILED_CCS;
2263                 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2264                         fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2265                 else
2266                         fb->modifier = I915_FORMAT_MOD_Y_TILED;
2267                 break;
2268         case PLANE_CTL_TILED_YF:
2269                 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2270                         fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2271                 else
2272                         fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2273                 break;
2274         default:
2275                 MISSING_CASE(tiling);
2276                 goto error;
2277         }
2278
2279         /*
2280          * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2281          * while i915 HW rotation is clockwise, thats why this swapping.
2282          */
2283         switch (val & PLANE_CTL_ROTATE_MASK) {
2284         case PLANE_CTL_ROTATE_0:
2285                 plane_config->rotation = DRM_MODE_ROTATE_0;
2286                 break;
2287         case PLANE_CTL_ROTATE_90:
2288                 plane_config->rotation = DRM_MODE_ROTATE_270;
2289                 break;
2290         case PLANE_CTL_ROTATE_180:
2291                 plane_config->rotation = DRM_MODE_ROTATE_180;
2292                 break;
2293         case PLANE_CTL_ROTATE_270:
2294                 plane_config->rotation = DRM_MODE_ROTATE_90;
2295                 break;
2296         }
2297
2298         if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
2299                 plane_config->rotation |= DRM_MODE_REFLECT_X;
2300
2301         /* 90/270 degree rotation would require extra work */
2302         if (drm_rotation_90_or_270(plane_config->rotation))
2303                 goto error;
2304
2305         base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
2306         plane_config->base = base;
2307
2308         offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2309
2310         val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2311         fb->height = ((val >> 16) & 0xffff) + 1;
2312         fb->width = ((val >> 0) & 0xffff) + 1;
2313
2314         val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2315         stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2316
2317         if (DISPLAY_VER(dev_priv) >= 13)
2318                 fb->pitches[0] = (val & PLANE_STRIDE_MASK_XELPD) * stride_mult;
2319         else
2320                 fb->pitches[0] = (val & PLANE_STRIDE_MASK) * stride_mult;
2321
2322         aligned_height = intel_fb_align_height(fb, 0, fb->height);
2323
2324         plane_config->size = fb->pitches[0] * aligned_height;
2325
2326         drm_dbg_kms(&dev_priv->drm,
2327                     "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2328                     crtc->base.name, plane->base.name, fb->width, fb->height,
2329                     fb->format->cpp[0] * 8, base, fb->pitches[0],
2330                     plane_config->size);
2331
2332         plane_config->fb = intel_fb;
2333         return;
2334
2335 error:
2336         kfree(intel_fb);
2337 }