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