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