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