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