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 !crtc_state->clear_psr2_sel_fetch)
890 return;
891
892 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0);
893 }
894
plane_has_normalizer(struct intel_plane * plane)895 static bool plane_has_normalizer(struct intel_plane *plane)
896 {
897 struct intel_display *display = to_intel_display(plane);
898
899 return HAS_PIXEL_NORMALIZER(display) && icl_is_hdr_plane(display, plane->id);
900 }
901
pixel_normalizer_value(const struct intel_plane_state * plane_state)902 static u32 pixel_normalizer_value(const struct intel_plane_state *plane_state)
903 {
904 if (!intel_fbc_need_pixel_normalizer(plane_state))
905 return 0;
906
907 return PLANE_PIXEL_NORMALIZE_ENABLE |
908 PLANE_PIXEL_NORMALIZE_NORM_FACTOR(PLANE_PIXEL_NORMALIZE_NORM_FACTOR_1_0);
909 }
910
911 static void
icl_plane_disable_arm(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state)912 icl_plane_disable_arm(struct intel_dsb *dsb,
913 struct intel_plane *plane,
914 const struct intel_crtc_state *crtc_state)
915 {
916 struct intel_display *display = to_intel_display(plane);
917 enum plane_id plane_id = plane->id;
918 enum pipe pipe = plane->pipe;
919
920 if (icl_is_hdr_plane(display, plane_id))
921 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id), 0);
922
923 skl_write_plane_wm(dsb, plane, crtc_state);
924
925 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state);
926
927 if (plane_has_normalizer(plane))
928 intel_de_write_dsb(display, dsb,
929 PLANE_PIXEL_NORMALIZE(plane->pipe, plane->id), 0);
930
931 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0);
932 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0);
933 }
934
935 static bool
skl_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)936 skl_plane_get_hw_state(struct intel_plane *plane,
937 enum pipe *pipe)
938 {
939 struct intel_display *display = to_intel_display(plane);
940 enum intel_display_power_domain power_domain;
941 enum plane_id plane_id = plane->id;
942 struct ref_tracker *wakeref;
943 bool ret;
944
945 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
946 wakeref = intel_display_power_get_if_enabled(display, power_domain);
947 if (!wakeref)
948 return false;
949
950 ret = intel_de_read(display, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
951
952 *pipe = plane->pipe;
953
954 intel_display_power_put(display, power_domain, wakeref);
955
956 return ret;
957 }
958
skl_plane_ctl_format(u32 pixel_format)959 static u32 skl_plane_ctl_format(u32 pixel_format)
960 {
961 switch (pixel_format) {
962 case DRM_FORMAT_C8:
963 return PLANE_CTL_FORMAT_INDEXED;
964 case DRM_FORMAT_RGB565:
965 return PLANE_CTL_FORMAT_RGB_565;
966 case DRM_FORMAT_XBGR8888:
967 case DRM_FORMAT_ABGR8888:
968 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
969 case DRM_FORMAT_XRGB8888:
970 case DRM_FORMAT_ARGB8888:
971 return PLANE_CTL_FORMAT_XRGB_8888;
972 case DRM_FORMAT_XBGR2101010:
973 case DRM_FORMAT_ABGR2101010:
974 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
975 case DRM_FORMAT_XRGB2101010:
976 case DRM_FORMAT_ARGB2101010:
977 return PLANE_CTL_FORMAT_XRGB_2101010;
978 case DRM_FORMAT_XBGR16161616F:
979 case DRM_FORMAT_ABGR16161616F:
980 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
981 case DRM_FORMAT_XRGB16161616F:
982 case DRM_FORMAT_ARGB16161616F:
983 return PLANE_CTL_FORMAT_XRGB_16161616F;
984 case DRM_FORMAT_XYUV8888:
985 return PLANE_CTL_FORMAT_XYUV;
986 case DRM_FORMAT_YUYV:
987 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YUYV;
988 case DRM_FORMAT_YVYU:
989 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YVYU;
990 case DRM_FORMAT_UYVY:
991 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_UYVY;
992 case DRM_FORMAT_VYUY:
993 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_VYUY;
994 case DRM_FORMAT_NV12:
995 return PLANE_CTL_FORMAT_NV12;
996 case DRM_FORMAT_P010:
997 return PLANE_CTL_FORMAT_P010;
998 case DRM_FORMAT_P012:
999 return PLANE_CTL_FORMAT_P012;
1000 case DRM_FORMAT_P016:
1001 return PLANE_CTL_FORMAT_P016;
1002 case DRM_FORMAT_Y210:
1003 return PLANE_CTL_FORMAT_Y210;
1004 case DRM_FORMAT_Y212:
1005 return PLANE_CTL_FORMAT_Y212;
1006 case DRM_FORMAT_Y216:
1007 return PLANE_CTL_FORMAT_Y216;
1008 case DRM_FORMAT_XVYU2101010:
1009 return PLANE_CTL_FORMAT_Y410;
1010 case DRM_FORMAT_XVYU12_16161616:
1011 return PLANE_CTL_FORMAT_Y412;
1012 case DRM_FORMAT_XVYU16161616:
1013 return PLANE_CTL_FORMAT_Y416;
1014 default:
1015 MISSING_CASE(pixel_format);
1016 }
1017
1018 return 0;
1019 }
1020
skl_plane_ctl_alpha(const struct intel_plane_state * plane_state)1021 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
1022 {
1023 if (!plane_state->hw.fb->format->has_alpha)
1024 return PLANE_CTL_ALPHA_DISABLE;
1025
1026 switch (plane_state->hw.pixel_blend_mode) {
1027 case DRM_MODE_BLEND_PIXEL_NONE:
1028 return PLANE_CTL_ALPHA_DISABLE;
1029 case DRM_MODE_BLEND_PREMULTI:
1030 return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
1031 case DRM_MODE_BLEND_COVERAGE:
1032 return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
1033 default:
1034 MISSING_CASE(plane_state->hw.pixel_blend_mode);
1035 return PLANE_CTL_ALPHA_DISABLE;
1036 }
1037 }
1038
glk_plane_color_ctl_alpha(const struct intel_plane_state * plane_state)1039 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
1040 {
1041 if (!plane_state->hw.fb->format->has_alpha)
1042 return PLANE_COLOR_ALPHA_DISABLE;
1043
1044 switch (plane_state->hw.pixel_blend_mode) {
1045 case DRM_MODE_BLEND_PIXEL_NONE:
1046 return PLANE_COLOR_ALPHA_DISABLE;
1047 case DRM_MODE_BLEND_PREMULTI:
1048 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
1049 case DRM_MODE_BLEND_COVERAGE:
1050 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
1051 default:
1052 MISSING_CASE(plane_state->hw.pixel_blend_mode);
1053 return PLANE_COLOR_ALPHA_DISABLE;
1054 }
1055 }
1056
skl_plane_ctl_tiling(u64 fb_modifier)1057 static u32 skl_plane_ctl_tiling(u64 fb_modifier)
1058 {
1059 switch (fb_modifier) {
1060 case DRM_FORMAT_MOD_LINEAR:
1061 break;
1062 case I915_FORMAT_MOD_X_TILED:
1063 return PLANE_CTL_TILED_X;
1064 case I915_FORMAT_MOD_Y_TILED:
1065 return PLANE_CTL_TILED_Y;
1066 case I915_FORMAT_MOD_4_TILED:
1067 return PLANE_CTL_TILED_4;
1068 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
1069 return PLANE_CTL_TILED_4 |
1070 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
1071 PLANE_CTL_CLEAR_COLOR_DISABLE;
1072 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
1073 return PLANE_CTL_TILED_4 |
1074 PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
1075 PLANE_CTL_CLEAR_COLOR_DISABLE;
1076 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
1077 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
1078 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
1079 return PLANE_CTL_TILED_4 |
1080 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
1081 PLANE_CTL_CLEAR_COLOR_DISABLE;
1082 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
1083 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
1084 case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
1085 return PLANE_CTL_TILED_4 | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
1086 case I915_FORMAT_MOD_4_TILED_BMG_CCS:
1087 case I915_FORMAT_MOD_4_TILED_LNL_CCS:
1088 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
1089 case I915_FORMAT_MOD_Y_TILED_CCS:
1090 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
1091 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
1092 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
1093 return PLANE_CTL_TILED_Y |
1094 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
1095 PLANE_CTL_CLEAR_COLOR_DISABLE;
1096 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
1097 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
1098 case I915_FORMAT_MOD_Yf_TILED:
1099 return PLANE_CTL_TILED_YF;
1100 case I915_FORMAT_MOD_Yf_TILED_CCS:
1101 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
1102 default:
1103 MISSING_CASE(fb_modifier);
1104 }
1105
1106 return 0;
1107 }
1108
skl_plane_ctl_rotate(unsigned int rotate)1109 static u32 skl_plane_ctl_rotate(unsigned int rotate)
1110 {
1111 switch (rotate) {
1112 case DRM_MODE_ROTATE_0:
1113 break;
1114 /*
1115 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
1116 * while i915 HW rotation is clockwise, that's why this swapping.
1117 */
1118 case DRM_MODE_ROTATE_90:
1119 return PLANE_CTL_ROTATE_270;
1120 case DRM_MODE_ROTATE_180:
1121 return PLANE_CTL_ROTATE_180;
1122 case DRM_MODE_ROTATE_270:
1123 return PLANE_CTL_ROTATE_90;
1124 default:
1125 MISSING_CASE(rotate);
1126 }
1127
1128 return 0;
1129 }
1130
icl_plane_ctl_flip(unsigned int reflect)1131 static u32 icl_plane_ctl_flip(unsigned int reflect)
1132 {
1133 switch (reflect) {
1134 case 0:
1135 break;
1136 case DRM_MODE_REFLECT_X:
1137 return PLANE_CTL_FLIP_HORIZONTAL;
1138 case DRM_MODE_REFLECT_Y:
1139 default:
1140 MISSING_CASE(reflect);
1141 }
1142
1143 return 0;
1144 }
1145
adlp_plane_ctl_arb_slots(const struct intel_plane_state * plane_state)1146 static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
1147 {
1148 const struct drm_framebuffer *fb = plane_state->hw.fb;
1149
1150 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
1151 switch (fb->format->cpp[0]) {
1152 case 2:
1153 return PLANE_CTL_ARB_SLOTS(1);
1154 default:
1155 return PLANE_CTL_ARB_SLOTS(0);
1156 }
1157 } else {
1158 switch (fb->format->cpp[0]) {
1159 case 8:
1160 return PLANE_CTL_ARB_SLOTS(3);
1161 case 4:
1162 return PLANE_CTL_ARB_SLOTS(1);
1163 default:
1164 return PLANE_CTL_ARB_SLOTS(0);
1165 }
1166 }
1167 }
1168
skl_plane_ctl_crtc(const struct intel_crtc_state * crtc_state)1169 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
1170 {
1171 struct intel_display *display = to_intel_display(crtc_state);
1172 u32 plane_ctl = 0;
1173
1174 if (DISPLAY_VER(display) >= 10)
1175 return plane_ctl;
1176
1177 if (crtc_state->gamma_enable)
1178 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
1179
1180 if (crtc_state->csc_enable)
1181 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
1182
1183 return plane_ctl;
1184 }
1185
skl_plane_ctl(const struct intel_plane_state * plane_state)1186 static u32 skl_plane_ctl(const struct intel_plane_state *plane_state)
1187 {
1188 struct intel_display *display = to_intel_display(plane_state);
1189 const struct drm_framebuffer *fb = plane_state->hw.fb;
1190 unsigned int rotation = plane_state->hw.rotation;
1191 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1192 u32 plane_ctl;
1193
1194 plane_ctl = PLANE_CTL_ENABLE;
1195
1196 if (DISPLAY_VER(display) < 10) {
1197 plane_ctl |= skl_plane_ctl_alpha(plane_state);
1198 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
1199
1200 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1201 plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
1202
1203 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1204 plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
1205 }
1206
1207 plane_ctl |= skl_plane_ctl_format(fb->format->format);
1208 plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
1209 plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
1210
1211 if (DISPLAY_VER(display) >= 11)
1212 plane_ctl |= icl_plane_ctl_flip(rotation &
1213 DRM_MODE_REFLECT_MASK);
1214
1215 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1216 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
1217 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1218 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
1219
1220 /* Wa_22012358565:adl-p */
1221 if (intel_display_wa(display, INTEL_DISPLAY_WA_22012358565))
1222 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
1223
1224 return plane_ctl;
1225 }
1226
glk_plane_color_ctl_crtc(const struct intel_crtc_state * crtc_state)1227 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
1228 {
1229 struct intel_display *display = to_intel_display(crtc_state);
1230 u32 plane_color_ctl = 0;
1231
1232 if (DISPLAY_VER(display) >= 11)
1233 return plane_color_ctl;
1234
1235 if (crtc_state->gamma_enable)
1236 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
1237
1238 if (crtc_state->csc_enable)
1239 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
1240
1241 return plane_color_ctl;
1242 }
1243
glk_plane_color_ctl(const struct intel_plane_state * plane_state)1244 static u32 glk_plane_color_ctl(const struct intel_plane_state *plane_state)
1245 {
1246 struct intel_display *display = to_intel_display(plane_state);
1247 const struct drm_framebuffer *fb = plane_state->hw.fb;
1248 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1249 u32 plane_color_ctl = 0;
1250
1251 plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
1252 plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
1253
1254 if (fb->format->is_yuv && !icl_is_hdr_plane(display, plane->id)) {
1255 switch (plane_state->hw.color_encoding) {
1256 case DRM_COLOR_YCBCR_BT709:
1257 plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
1258 break;
1259 case DRM_COLOR_YCBCR_BT2020:
1260 plane_color_ctl |=
1261 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
1262 break;
1263 default:
1264 plane_color_ctl |=
1265 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
1266 }
1267 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1268 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
1269 } else if (fb->format->is_yuv) {
1270 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
1271 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1272 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
1273 }
1274
1275 if (plane_state->force_black)
1276 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
1277
1278 if (plane_state->hw.degamma_lut)
1279 plane_color_ctl |= PLANE_COLOR_PRE_CSC_GAMMA_ENABLE;
1280
1281 if (plane_state->hw.ctm)
1282 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
1283
1284 if (plane_state->hw.gamma_lut) {
1285 plane_color_ctl &= ~PLANE_COLOR_PLANE_GAMMA_DISABLE;
1286 if (drm_color_lut32_size(plane_state->hw.gamma_lut) != 32)
1287 plane_color_ctl |= PLANE_COLOR_POST_CSC_GAMMA_MULTSEG_ENABLE;
1288 }
1289
1290 return plane_color_ctl;
1291 }
1292
skl_surf_address(const struct intel_plane_state * plane_state,int color_plane)1293 static u32 skl_surf_address(const struct intel_plane_state *plane_state,
1294 int color_plane)
1295 {
1296 struct intel_display *display = to_intel_display(plane_state);
1297 const struct drm_framebuffer *fb = plane_state->hw.fb;
1298 u32 offset = plane_state->view.color_plane[color_plane].offset;
1299
1300 if (intel_fb_uses_dpt(fb)) {
1301 drm_WARN_ON(display->drm, offset & 0x1fffff);
1302 return offset >> 9;
1303 } else {
1304 drm_WARN_ON(display->drm, offset & 0xfff);
1305 return offset;
1306 }
1307 }
1308
icl_plane_color_plane(const struct intel_plane_state * plane_state)1309 static int icl_plane_color_plane(const struct intel_plane_state *plane_state)
1310 {
1311 if (plane_state->planar_linked_plane && !plane_state->is_y_plane)
1312 return 1;
1313 else
1314 return 0;
1315 }
1316
skl_plane_surf_offset(const struct intel_plane_state * plane_state)1317 static u32 skl_plane_surf_offset(const struct intel_plane_state *plane_state)
1318 {
1319 int color_plane = icl_plane_color_plane(plane_state);
1320 u32 plane_surf;
1321
1322 plane_surf = skl_surf_address(plane_state, color_plane);
1323
1324 if (plane_state->decrypt)
1325 plane_surf |= PLANE_SURF_DECRYPT;
1326
1327 return plane_surf;
1328 }
1329
skl_plane_aux_dist(const struct intel_plane_state * plane_state,int color_plane)1330 u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state,
1331 int color_plane)
1332 {
1333 struct intel_display *display = to_intel_display(plane_state);
1334 const struct drm_framebuffer *fb = plane_state->hw.fb;
1335 int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1336 u32 aux_dist;
1337
1338 if (!aux_plane)
1339 return 0;
1340
1341 aux_dist = skl_surf_address(plane_state, aux_plane) -
1342 skl_surf_address(plane_state, color_plane);
1343
1344 if (DISPLAY_VER(display) < 12)
1345 aux_dist |= PLANE_AUX_STRIDE(skl_plane_stride(plane_state, aux_plane));
1346
1347 return aux_dist;
1348 }
1349
skl_plane_keyval(const struct intel_plane_state * plane_state)1350 static u32 skl_plane_keyval(const struct intel_plane_state *plane_state)
1351 {
1352 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1353
1354 return key->min_value;
1355 }
1356
skl_plane_keymax(const struct intel_plane_state * plane_state)1357 static u32 skl_plane_keymax(const struct intel_plane_state *plane_state)
1358 {
1359 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1360 u8 alpha = plane_state->hw.alpha >> 8;
1361
1362 return (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
1363 }
1364
skl_plane_keymsk(const struct intel_plane_state * plane_state)1365 static u32 skl_plane_keymsk(const struct intel_plane_state *plane_state)
1366 {
1367 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1368 u8 alpha = plane_state->hw.alpha >> 8;
1369 u32 keymsk;
1370
1371 keymsk = key->channel_mask & 0x7ffffff;
1372 if (alpha < 0xff)
1373 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
1374
1375 return keymsk;
1376 }
1377
icl_plane_csc_load_black(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state)1378 static void icl_plane_csc_load_black(struct intel_dsb *dsb,
1379 struct intel_plane *plane,
1380 const struct intel_crtc_state *crtc_state)
1381 {
1382 struct intel_display *display = to_intel_display(plane);
1383 enum plane_id plane_id = plane->id;
1384 enum pipe pipe = plane->pipe;
1385
1386 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 0), 0);
1387 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 1), 0);
1388
1389 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 2), 0);
1390 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 3), 0);
1391
1392 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 4), 0);
1393 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 5), 0);
1394
1395 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0);
1396 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0);
1397 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0);
1398
1399 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0);
1400 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0);
1401 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
1402 }
1403
1404 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)1405 skl_plane_update_noarm(struct intel_dsb *dsb,
1406 struct intel_plane *plane,
1407 const struct intel_crtc_state *crtc_state,
1408 const struct intel_plane_state *plane_state)
1409 {
1410 struct intel_display *display = to_intel_display(plane);
1411 enum plane_id plane_id = plane->id;
1412 enum pipe pipe = plane->pipe;
1413 u32 stride = skl_plane_stride(plane_state, 0);
1414 int crtc_x = plane_state->uapi.dst.x1;
1415 int crtc_y = plane_state->uapi.dst.y1;
1416 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1417 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1418
1419 /* The scaler will handle the output position */
1420 if (plane_state->scaler_id >= 0) {
1421 crtc_x = 0;
1422 crtc_y = 0;
1423 }
1424
1425 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id),
1426 PLANE_STRIDE_(stride));
1427 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id),
1428 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1429 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id),
1430 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1431
1432 skl_write_plane_wm(dsb, plane, crtc_state);
1433 }
1434
1435 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)1436 skl_plane_update_arm(struct intel_dsb *dsb,
1437 struct intel_plane *plane,
1438 const struct intel_crtc_state *crtc_state,
1439 const struct intel_plane_state *plane_state)
1440 {
1441 struct intel_display *display = to_intel_display(plane);
1442 enum plane_id plane_id = plane->id;
1443 enum pipe pipe = plane->pipe;
1444 u32 x = plane_state->view.color_plane[0].x;
1445 u32 y = plane_state->view.color_plane[0].y;
1446 u32 plane_ctl, plane_color_ctl = 0;
1447
1448 plane_ctl = plane_state->ctl |
1449 skl_plane_ctl_crtc(crtc_state);
1450
1451 /* see intel_plane_atomic_calc_changes() */
1452 if (plane->need_async_flip_toggle_wa &&
1453 crtc_state->async_flip_planes & BIT(plane->id))
1454 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1455
1456 if (DISPLAY_VER(display) >= 10)
1457 plane_color_ctl = plane_state->color_ctl |
1458 glk_plane_color_ctl_crtc(crtc_state);
1459
1460 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id),
1461 skl_plane_keyval(plane_state));
1462 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id),
1463 skl_plane_keymsk(plane_state));
1464 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id),
1465 skl_plane_keymax(plane_state));
1466
1467 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id),
1468 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1469
1470 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id),
1471 skl_plane_aux_dist(plane_state, 0));
1472
1473 intel_de_write_dsb(display, dsb, PLANE_AUX_OFFSET(pipe, plane_id),
1474 PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
1475 PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
1476
1477 if (DISPLAY_VER(display) >= 10)
1478 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id),
1479 plane_color_ctl);
1480
1481 /*
1482 * Enable the scaler before the plane so that we don't
1483 * get a catastrophic underrun even if the two operations
1484 * end up happening in two different frames.
1485 *
1486 * TODO: split into noarm+arm pair
1487 */
1488 if (plane_state->scaler_id >= 0)
1489 skl_program_plane_scaler(dsb, plane, crtc_state, plane_state);
1490
1491 /*
1492 * The control register self-arms if the plane was previously
1493 * disabled. Try to make the plane enable atomic by writing
1494 * the control register just before the surface register.
1495 */
1496 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1497 plane_ctl);
1498 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1499 plane_state->surf);
1500 }
1501
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)1502 static void icl_plane_update_sel_fetch_noarm(struct intel_dsb *dsb,
1503 struct intel_plane *plane,
1504 const struct intel_crtc_state *crtc_state,
1505 const struct intel_plane_state *plane_state,
1506 int color_plane)
1507 {
1508 struct intel_display *display = to_intel_display(plane);
1509 enum pipe pipe = plane->pipe;
1510 const struct drm_rect *clip;
1511 u32 val;
1512 int x, y;
1513
1514 if (!crtc_state->enable_psr2_sel_fetch)
1515 return;
1516
1517 clip = &plane_state->psr2_sel_fetch_area;
1518
1519 if (crtc_state->enable_psr2_su_region_et)
1520 y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1);
1521 else
1522 y = (clip->y1 + plane_state->uapi.dst.y1);
1523 val = y << 16;
1524 val |= plane_state->uapi.dst.x1;
1525 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_POS(pipe, plane->id), val);
1526
1527 x = plane_state->view.color_plane[color_plane].x;
1528
1529 /*
1530 * From Bspec: UV surface Start Y Position = half of Y plane Y
1531 * start position.
1532 */
1533 if (!color_plane)
1534 y = plane_state->view.color_plane[color_plane].y + clip->y1;
1535 else
1536 y = plane_state->view.color_plane[color_plane].y + DIV_ROUND_UP(clip->y1, 2);
1537
1538 val = y << 16 | x;
1539
1540 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_OFFSET(pipe, plane->id), val);
1541
1542 /* Sizes are 0 based */
1543 val = (drm_rect_height(clip) - 1) << 16;
1544 val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1;
1545 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val);
1546 }
1547
1548 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)1549 icl_plane_update_noarm(struct intel_dsb *dsb,
1550 struct intel_plane *plane,
1551 const struct intel_crtc_state *crtc_state,
1552 const struct intel_plane_state *plane_state)
1553 {
1554 struct intel_display *display = to_intel_display(plane);
1555 enum plane_id plane_id = plane->id;
1556 enum pipe pipe = plane->pipe;
1557 int color_plane = icl_plane_color_plane(plane_state);
1558 u32 stride = skl_plane_stride(plane_state, color_plane);
1559 const struct drm_framebuffer *fb = plane_state->hw.fb;
1560 int crtc_x = plane_state->uapi.dst.x1;
1561 int crtc_y = plane_state->uapi.dst.y1;
1562 int x = plane_state->view.color_plane[color_plane].x;
1563 int y = plane_state->view.color_plane[color_plane].y;
1564 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1565 int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1566 u32 plane_color_ctl;
1567
1568 plane_color_ctl = plane_state->color_ctl |
1569 glk_plane_color_ctl_crtc(crtc_state);
1570
1571 intel_color_plane_program_pipeline(dsb, plane_state);
1572
1573 /* The scaler will handle the output position */
1574 if (plane_state->scaler_id >= 0) {
1575 crtc_x = 0;
1576 crtc_y = 0;
1577 }
1578
1579 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id),
1580 PLANE_STRIDE_(stride));
1581 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id),
1582 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1583 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id),
1584 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1585
1586 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id),
1587 skl_plane_keyval(plane_state));
1588 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id),
1589 skl_plane_keymsk(plane_state));
1590 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id),
1591 skl_plane_keymax(plane_state));
1592
1593 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id),
1594 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1595
1596 if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
1597 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 0),
1598 lower_32_bits(plane_state->ccval));
1599 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 1),
1600 upper_32_bits(plane_state->ccval));
1601 }
1602
1603 /* FLAT CCS doesn't need to program AUX_DIST */
1604 if (HAS_AUX_DIST(display))
1605 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id),
1606 skl_plane_aux_dist(plane_state, color_plane));
1607
1608 if (icl_is_hdr_plane(display, plane_id))
1609 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id),
1610 plane_state->cus_ctl);
1611
1612 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id),
1613 plane_color_ctl);
1614
1615 if (fb->format->is_yuv && icl_is_hdr_plane(display, plane_id))
1616 icl_program_input_csc(dsb, plane, plane_state);
1617
1618 skl_write_plane_wm(dsb, plane, crtc_state);
1619
1620 /*
1621 * FIXME: pxp session invalidation can hit any time even at time of commit
1622 * or after the commit, display content will be garbage.
1623 */
1624 if (plane_state->force_black)
1625 icl_plane_csc_load_black(dsb, plane, crtc_state);
1626
1627 icl_plane_update_sel_fetch_noarm(dsb, plane, crtc_state, plane_state, color_plane);
1628 }
1629
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)1630 static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb,
1631 struct intel_plane *plane,
1632 const struct intel_crtc_state *crtc_state,
1633 const struct intel_plane_state *plane_state)
1634 {
1635 struct intel_display *display = to_intel_display(plane);
1636 enum pipe pipe = plane->pipe;
1637
1638 if (crtc_state->enable_psr2_sel_fetch &&
1639 drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
1640 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id),
1641 SEL_FETCH_PLANE_CTL_ENABLE);
1642 else
1643 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state);
1644 }
1645
1646 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)1647 icl_plane_update_arm(struct intel_dsb *dsb,
1648 struct intel_plane *plane,
1649 const struct intel_crtc_state *crtc_state,
1650 const struct intel_plane_state *plane_state)
1651 {
1652 struct intel_display *display = to_intel_display(plane);
1653 enum plane_id plane_id = plane->id;
1654 enum pipe pipe = plane->pipe;
1655 u32 plane_ctl;
1656
1657 plane_ctl = plane_state->ctl |
1658 skl_plane_ctl_crtc(crtc_state);
1659
1660 /*
1661 * Enable the scaler before the plane so that we don't
1662 * get a catastrophic underrun even if the two operations
1663 * end up happening in two different frames.
1664 *
1665 * TODO: split into noarm+arm pair
1666 */
1667 if (plane_state->scaler_id >= 0)
1668 skl_program_plane_scaler(dsb, plane, crtc_state, plane_state);
1669
1670 icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
1671
1672 intel_color_plane_commit_arm(dsb, plane_state);
1673
1674 /*
1675 * In order to have FBC for fp16 formats pixel normalizer block must be
1676 * active. For FP16 formats, use normalization factor as 1.0 and enable
1677 * the block.
1678 */
1679 if (plane_has_normalizer(plane))
1680 intel_de_write_dsb(display, dsb,
1681 PLANE_PIXEL_NORMALIZE(plane->pipe, plane->id),
1682 pixel_normalizer_value(plane_state));
1683
1684 /*
1685 * The control register self-arms if the plane was previously
1686 * disabled. Try to make the plane enable atomic by writing
1687 * the control register just before the surface register.
1688 */
1689 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1690 plane_ctl);
1691 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1692 plane_state->surf);
1693 }
1694
skl_plane_capture_error(struct intel_crtc * crtc,struct intel_plane * plane,struct intel_plane_error * error)1695 static void skl_plane_capture_error(struct intel_crtc *crtc,
1696 struct intel_plane *plane,
1697 struct intel_plane_error *error)
1698 {
1699 struct intel_display *display = to_intel_display(plane);
1700
1701 error->ctl = intel_de_read(display, PLANE_CTL(crtc->pipe, plane->id));
1702 error->surf = intel_de_read(display, PLANE_SURF(crtc->pipe, plane->id));
1703 error->surflive = intel_de_read(display, PLANE_SURFLIVE(crtc->pipe, plane->id));
1704 }
1705
1706 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)1707 skl_plane_async_flip(struct intel_dsb *dsb,
1708 struct intel_plane *plane,
1709 const struct intel_crtc_state *crtc_state,
1710 const struct intel_plane_state *plane_state,
1711 bool async_flip)
1712 {
1713 struct intel_display *display = to_intel_display(plane);
1714 enum plane_id plane_id = plane->id;
1715 enum pipe pipe = plane->pipe;
1716 u32 plane_ctl = plane_state->ctl;
1717 u32 plane_surf = plane_state->surf;
1718
1719 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1720
1721 if (async_flip) {
1722 if (DISPLAY_VER(display) >= 30)
1723 plane_surf |= PLANE_SURF_ASYNC_UPDATE;
1724 else
1725 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1726 }
1727
1728 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1729 plane_ctl);
1730 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1731 plane_surf);
1732 }
1733
intel_format_is_p01x(u32 format)1734 static bool intel_format_is_p01x(u32 format)
1735 {
1736 switch (format) {
1737 case DRM_FORMAT_P010:
1738 case DRM_FORMAT_P012:
1739 case DRM_FORMAT_P016:
1740 return true;
1741 default:
1742 return false;
1743 }
1744 }
1745
skl_plane_check_fb(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1746 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1747 const struct intel_plane_state *plane_state)
1748 {
1749 struct intel_display *display = to_intel_display(plane_state);
1750 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1751 const struct drm_framebuffer *fb = plane_state->hw.fb;
1752 unsigned int rotation = plane_state->hw.rotation;
1753
1754 if (!fb)
1755 return 0;
1756
1757 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1758 intel_fb_is_ccs_modifier(fb->modifier)) {
1759 drm_dbg_kms(display->drm,
1760 "[PLANE:%d:%s] RC support only with 0/180 degree rotation (%x)\n",
1761 plane->base.base.id, plane->base.name, rotation);
1762 return -EINVAL;
1763 }
1764
1765 if (rotation & DRM_MODE_REFLECT_X &&
1766 fb->modifier == DRM_FORMAT_MOD_LINEAR &&
1767 DISPLAY_VER(display) < 35) {
1768 drm_dbg_kms(display->drm,
1769 "[PLANE:%d:%s] horizontal flip is not supported with linear surface formats\n",
1770 plane->base.base.id, plane->base.name);
1771 return -EINVAL;
1772 }
1773
1774 /*
1775 * Display20 onward tile4 hflip is not supported
1776 */
1777 if (rotation & DRM_MODE_REFLECT_X &&
1778 intel_fb_is_tile4_modifier(fb->modifier) &&
1779 DISPLAY_VER(display) >= 20) {
1780 drm_dbg_kms(display->drm,
1781 "[PLANE:%d:%s] horizontal flip is not supported with tile4 surface formats\n",
1782 plane->base.base.id, plane->base.name);
1783 return -EINVAL;
1784 }
1785
1786 if (drm_rotation_90_or_270(rotation)) {
1787 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
1788 drm_dbg_kms(display->drm,
1789 "[PLANE:%d:%s] Y/Yf tiling required for 90/270!\n",
1790 plane->base.base.id, plane->base.name);
1791 return -EINVAL;
1792 }
1793
1794 /*
1795 * 90/270 is not allowed with RGB64 16:16:16:16 and
1796 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1797 */
1798 switch (fb->format->format) {
1799 case DRM_FORMAT_RGB565:
1800 if (DISPLAY_VER(display) >= 11)
1801 break;
1802 fallthrough;
1803 case DRM_FORMAT_C8:
1804 case DRM_FORMAT_XRGB16161616F:
1805 case DRM_FORMAT_XBGR16161616F:
1806 case DRM_FORMAT_ARGB16161616F:
1807 case DRM_FORMAT_ABGR16161616F:
1808 case DRM_FORMAT_Y210:
1809 case DRM_FORMAT_Y212:
1810 case DRM_FORMAT_Y216:
1811 case DRM_FORMAT_XVYU12_16161616:
1812 case DRM_FORMAT_XVYU16161616:
1813 drm_dbg_kms(display->drm,
1814 "[PLANE:%d:%s] unsupported pixel format %p4cc for 90/270!\n",
1815 plane->base.base.id, plane->base.name, &fb->format->format);
1816 return -EINVAL;
1817 default:
1818 break;
1819 }
1820 }
1821
1822 /* Y-tiling is not supported in IF-ID Interlace mode */
1823 if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1824 fb->modifier != DRM_FORMAT_MOD_LINEAR &&
1825 fb->modifier != I915_FORMAT_MOD_X_TILED) {
1826 drm_dbg_kms(display->drm,
1827 "[PLANE:%d:%s] Y/Yf tiling not supported in IF-ID mode\n",
1828 plane->base.base.id, plane->base.name);
1829 return -EINVAL;
1830 }
1831
1832 /* Wa_1606054188:tgl,adl-s */
1833 if ((display->platform.alderlake_s || display->platform.tigerlake) &&
1834 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1835 intel_format_is_p01x(fb->format->format)) {
1836 drm_dbg_kms(display->drm,
1837 "[PLANE:%d:%s] source color keying not supported with P01x formats\n",
1838 plane->base.base.id, plane->base.name);
1839 return -EINVAL;
1840 }
1841
1842 return 0;
1843 }
1844
skl_plane_check_dst_coordinates(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1845 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1846 const struct intel_plane_state *plane_state)
1847 {
1848 struct intel_display *display = to_intel_display(plane_state);
1849 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1850 int crtc_x = plane_state->uapi.dst.x1;
1851 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1852 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
1853
1854 /*
1855 * Display WA #1175: glk
1856 * Planes other than the cursor may cause FIFO underflow and display
1857 * corruption if starting less than 4 pixels from the right edge of
1858 * the screen.
1859 * Besides the above WA fix the similar problem, where planes other
1860 * than the cursor ending less than 4 pixels from the left edge of the
1861 * screen may cause FIFO underflow and display corruption.
1862 */
1863 if (DISPLAY_VER(display) == 10 &&
1864 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1865 drm_dbg_kms(display->drm,
1866 "[PLANE:%d:%s] requested plane X %s position %d invalid (valid range %d-%d)\n",
1867 plane->base.base.id, plane->base.name,
1868 crtc_x + crtc_w < 4 ? "end" : "start",
1869 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1870 4, pipe_src_w - 4);
1871 return -ERANGE;
1872 }
1873
1874 return 0;
1875 }
1876
skl_plane_check_nv12_rotation(const struct intel_plane_state * plane_state)1877 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1878 {
1879 struct intel_display *display = to_intel_display(plane_state);
1880 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1881 const struct drm_framebuffer *fb = plane_state->hw.fb;
1882 unsigned int rotation = plane_state->hw.rotation;
1883 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1884
1885 /* Display WA #1106 */
1886 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1887 src_w & 3 &&
1888 (rotation == DRM_MODE_ROTATE_270 ||
1889 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1890 drm_dbg_kms(display->drm,
1891 "[PLANE:%d:%s] src width must be multiple of 4 for rotated planar YUV\n",
1892 plane->base.base.id, plane->base.name);
1893 return -EINVAL;
1894 }
1895
1896 return 0;
1897 }
1898
skl_plane_max_scale(struct intel_display * display,const struct drm_framebuffer * fb)1899 static int skl_plane_max_scale(struct intel_display *display,
1900 const struct drm_framebuffer *fb)
1901 {
1902 /*
1903 * We don't yet know the final source width nor
1904 * whether we can use the HQ scaler mode. Assume
1905 * the best case.
1906 * FIXME need to properly check this later.
1907 */
1908 if (DISPLAY_VER(display) >= 10 ||
1909 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1910 return 0x30000 - 1;
1911 else
1912 return 0x20000 - 1;
1913 }
1914
intel_plane_min_width(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)1915 static int intel_plane_min_width(struct intel_plane *plane,
1916 const struct drm_framebuffer *fb,
1917 int color_plane,
1918 unsigned int rotation)
1919 {
1920 if (plane->min_width)
1921 return plane->min_width(fb, color_plane, rotation);
1922 else
1923 return 1;
1924 }
1925
intel_plane_min_height(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)1926 static int intel_plane_min_height(struct intel_plane *plane,
1927 const struct drm_framebuffer *fb,
1928 int color_plane,
1929 unsigned int rotation)
1930 {
1931 return 1;
1932 }
1933
intel_plane_max_width(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)1934 int intel_plane_max_width(struct intel_plane *plane,
1935 const struct drm_framebuffer *fb,
1936 int color_plane,
1937 unsigned int rotation)
1938 {
1939 if (plane->max_width)
1940 return plane->max_width(fb, color_plane, rotation);
1941 else
1942 return INT_MAX;
1943 }
1944
intel_plane_max_height(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)1945 int intel_plane_max_height(struct intel_plane *plane,
1946 const struct drm_framebuffer *fb,
1947 int color_plane,
1948 unsigned int rotation)
1949 {
1950 if (plane->max_height)
1951 return plane->max_height(fb, color_plane, rotation);
1952 else
1953 return INT_MAX;
1954 }
1955
1956 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)1957 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1958 int main_x, int main_y, u32 main_offset,
1959 int ccs_plane)
1960 {
1961 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1962 const struct drm_framebuffer *fb = plane_state->hw.fb;
1963 int aux_x = plane_state->view.color_plane[ccs_plane].x;
1964 int aux_y = plane_state->view.color_plane[ccs_plane].y;
1965 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1966 unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane);
1967 int hsub;
1968 int vsub;
1969
1970 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1971 while (aux_offset >= main_offset && aux_y <= main_y) {
1972 int x, y;
1973
1974 if (aux_x == main_x && aux_y == main_y)
1975 break;
1976
1977 if (aux_offset == 0)
1978 break;
1979
1980 x = aux_x / hsub;
1981 y = aux_y / vsub;
1982 aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1983 plane_state,
1984 ccs_plane,
1985 aux_offset,
1986 aux_offset - alignment);
1987 aux_x = x * hsub + aux_x % hsub;
1988 aux_y = y * vsub + aux_y % vsub;
1989 }
1990
1991 if (aux_x != main_x || aux_y != main_y)
1992 return false;
1993
1994 plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1995 plane_state->view.color_plane[ccs_plane].x = aux_x;
1996 plane_state->view.color_plane[ccs_plane].y = aux_y;
1997
1998 return true;
1999 }
2000
2001
skl_calc_main_surface_offset(const struct intel_plane_state * plane_state,int * x,int * y,u32 * offset)2002 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
2003 int *x, int *y, u32 *offset)
2004 {
2005 struct intel_display *display = to_intel_display(plane_state);
2006 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2007 const struct drm_framebuffer *fb = plane_state->hw.fb;
2008 int aux_plane = skl_main_to_aux_plane(fb, 0);
2009 u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
2010 unsigned int alignment = plane->min_alignment(plane, fb, 0);
2011 int w = drm_rect_width(&plane_state->uapi.src) >> 16;
2012
2013 intel_add_fb_offsets(x, y, plane_state, 0);
2014 *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
2015 if (drm_WARN_ON(display->drm, alignment && !is_power_of_2(alignment)))
2016 return -EINVAL;
2017
2018 /*
2019 * AUX surface offset is specified as the distance from the
2020 * main surface offset, and it must be non-negative. Make
2021 * sure that is what we will get.
2022 */
2023 if (aux_plane && *offset > aux_offset)
2024 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
2025 *offset,
2026 aux_offset & ~(alignment - 1));
2027
2028 /*
2029 * When using an X-tiled surface, the plane blows up
2030 * if the x offset + width exceed the stride.
2031 *
2032 * TODO: linear and Y-tiled seem fine, Yf untested,
2033 */
2034 if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
2035 int cpp = fb->format->cpp[0];
2036
2037 while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
2038 if (*offset == 0) {
2039 drm_dbg_kms(display->drm,
2040 "[PLANE:%d:%s] unable to find suitable display surface offset due to X-tiling\n",
2041 plane->base.base.id, plane->base.name);
2042 return -EINVAL;
2043 }
2044
2045 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
2046 *offset,
2047 *offset - alignment);
2048 }
2049 }
2050
2051 return 0;
2052 }
2053
skl_check_main_surface(struct intel_plane_state * plane_state)2054 static int skl_check_main_surface(struct intel_plane_state *plane_state)
2055 {
2056 struct intel_display *display = to_intel_display(plane_state);
2057 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2058 const struct drm_framebuffer *fb = plane_state->hw.fb;
2059 unsigned int rotation = plane_state->hw.rotation;
2060 int x = plane_state->uapi.src.x1 >> 16;
2061 int y = plane_state->uapi.src.y1 >> 16;
2062 int w = drm_rect_width(&plane_state->uapi.src) >> 16;
2063 int h = drm_rect_height(&plane_state->uapi.src) >> 16;
2064 int min_width = intel_plane_min_width(plane, fb, 0, rotation);
2065 int min_height = intel_plane_min_height(plane, fb, 0, rotation);
2066 int max_width = intel_plane_max_width(plane, fb, 0, rotation);
2067 int max_height = intel_plane_max_height(plane, fb, 0, rotation);
2068 unsigned int alignment = plane->min_alignment(plane, fb, 0);
2069 int aux_plane = skl_main_to_aux_plane(fb, 0);
2070 u32 offset;
2071 int ret;
2072
2073 if (w > max_width || w < min_width || h > max_height || h < min_height) {
2074 drm_dbg_kms(display->drm,
2075 "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx%d max: %dx%d)\n",
2076 plane->base.base.id, plane->base.name,
2077 w, h, min_width, min_height, max_width, max_height);
2078 return -EINVAL;
2079 }
2080
2081 ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
2082 if (ret)
2083 return ret;
2084
2085 /*
2086 * CCS AUX surface doesn't have its own x/y offsets, we must make sure
2087 * they match with the main surface x/y offsets. On DG2
2088 * there's no aux plane on fb so skip this checking.
2089 */
2090 if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) {
2091 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
2092 offset, aux_plane)) {
2093 if (offset == 0)
2094 break;
2095
2096 offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
2097 offset, offset - alignment);
2098 }
2099
2100 if (x != plane_state->view.color_plane[aux_plane].x ||
2101 y != plane_state->view.color_plane[aux_plane].y) {
2102 drm_dbg_kms(display->drm,
2103 "[PLANE:%d:%s] unable to find suitable display surface offset due to CCS\n",
2104 plane->base.base.id, plane->base.name);
2105 return -EINVAL;
2106 }
2107 }
2108
2109 if (DISPLAY_VER(display) >= 13)
2110 drm_WARN_ON(display->drm, x > 65535 || y > 65535);
2111 else
2112 drm_WARN_ON(display->drm, x > 8191 || y > 8191);
2113
2114 plane_state->view.color_plane[0].offset = offset;
2115 plane_state->view.color_plane[0].x = x;
2116 plane_state->view.color_plane[0].y = y;
2117
2118 /*
2119 * Put the final coordinates back so that the src
2120 * coordinate checks will see the right values.
2121 */
2122 drm_rect_translate_to(&plane_state->uapi.src,
2123 x << 16, y << 16);
2124
2125 return 0;
2126 }
2127
skl_check_nv12_aux_surface(struct intel_plane_state * plane_state)2128 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
2129 {
2130 struct intel_display *display = to_intel_display(plane_state);
2131 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2132 const struct drm_framebuffer *fb = plane_state->hw.fb;
2133 unsigned int rotation = plane_state->hw.rotation;
2134 int uv_plane = 1;
2135 int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
2136 skl_main_to_aux_plane(fb, uv_plane) : 0;
2137 int min_width = intel_plane_min_width(plane, fb, uv_plane, rotation);
2138 int min_height = intel_plane_min_height(plane, fb, uv_plane, rotation);
2139 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
2140 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
2141
2142 /*
2143 * UV (chroma) start/size = ceiling(half of the *integer* Y plane
2144 * start/size), i.e. the value the luma surface programs (src >> 16),
2145 * not the raw U16.16. A bigjoiner seam mapped through the scaler can
2146 * give a fractional luma src; ceiling that directly would round the
2147 * chroma one column too far and read past the chroma surface.
2148 */
2149 int luma_x = plane_state->uapi.src.x1 >> 16;
2150 int luma_y = plane_state->uapi.src.y1 >> 16;
2151 int luma_w = drm_rect_width(&plane_state->uapi.src) >> 16;
2152 int luma_h = drm_rect_height(&plane_state->uapi.src) >> 16;
2153 int x = DIV_ROUND_UP(luma_x, 2);
2154 int y = DIV_ROUND_UP(luma_y, 2);
2155 int w = DIV_ROUND_UP(luma_x + luma_w, 2) - x;
2156 int h = DIV_ROUND_UP(luma_y + luma_h, 2) - y;
2157 u32 offset;
2158
2159 /* FIXME not quite sure how/if these apply to the chroma plane */
2160 if (w > max_width || w < min_width || h > max_height || h < min_height) {
2161 drm_dbg_kms(display->drm,
2162 "[PLANE:%d:%s] requested CbCr source size %dx%d outside limits (min: %dx%d max: %dx%d)\n",
2163 plane->base.base.id, plane->base.name,
2164 w, h, min_width, min_height, max_width, max_height);
2165 return -EINVAL;
2166 }
2167
2168 intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
2169 offset = intel_plane_compute_aligned_offset(&x, &y,
2170 plane_state, uv_plane);
2171
2172 if (ccs_plane) {
2173 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
2174 unsigned int alignment = plane->min_alignment(plane, fb, uv_plane);
2175
2176 if (offset > aux_offset)
2177 offset = intel_plane_adjust_aligned_offset(&x, &y,
2178 plane_state,
2179 uv_plane,
2180 offset,
2181 aux_offset & ~(alignment - 1));
2182
2183 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
2184 offset, ccs_plane)) {
2185 if (offset == 0)
2186 break;
2187
2188 offset = intel_plane_adjust_aligned_offset(&x, &y,
2189 plane_state,
2190 uv_plane,
2191 offset, offset - alignment);
2192 }
2193
2194 if (x != plane_state->view.color_plane[ccs_plane].x ||
2195 y != plane_state->view.color_plane[ccs_plane].y) {
2196 drm_dbg_kms(display->drm,
2197 "[PLANE:%d:%s] unable to find suitable display surface offset due to CCS\n",
2198 plane->base.base.id, plane->base.name);
2199 return -EINVAL;
2200 }
2201 }
2202
2203 if (DISPLAY_VER(display) >= 13)
2204 drm_WARN_ON(display->drm, x > 65535 || y > 65535);
2205 else
2206 drm_WARN_ON(display->drm, x > 8191 || y > 8191);
2207
2208 plane_state->view.color_plane[uv_plane].offset = offset;
2209 plane_state->view.color_plane[uv_plane].x = x;
2210 plane_state->view.color_plane[uv_plane].y = y;
2211
2212 return 0;
2213 }
2214
skl_check_ccs_aux_surface(struct intel_plane_state * plane_state)2215 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
2216 {
2217 const struct drm_framebuffer *fb = plane_state->hw.fb;
2218 int src_x = plane_state->uapi.src.x1 >> 16;
2219 int src_y = plane_state->uapi.src.y1 >> 16;
2220 u32 offset;
2221 int ccs_plane;
2222
2223 for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
2224 int main_hsub, main_vsub;
2225 int hsub, vsub;
2226 int x, y;
2227
2228 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane))
2229 continue;
2230
2231 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
2232 skl_ccs_to_main_plane(fb, ccs_plane));
2233 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
2234
2235 hsub *= main_hsub;
2236 vsub *= main_vsub;
2237 x = src_x / hsub;
2238 y = src_y / vsub;
2239
2240 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
2241
2242 offset = intel_plane_compute_aligned_offset(&x, &y,
2243 plane_state,
2244 ccs_plane);
2245
2246 plane_state->view.color_plane[ccs_plane].offset = offset;
2247 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
2248 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
2249 }
2250
2251 return 0;
2252 }
2253
skl_check_plane_surface(struct intel_plane_state * plane_state)2254 static int skl_check_plane_surface(struct intel_plane_state *plane_state)
2255 {
2256 const struct drm_framebuffer *fb = plane_state->hw.fb;
2257 int ret;
2258
2259 ret = intel_plane_compute_gtt(plane_state);
2260 if (ret)
2261 return ret;
2262
2263 if (!plane_state->uapi.visible)
2264 return 0;
2265
2266 /*
2267 * Handle the AUX surface first since the main surface setup depends on
2268 * it.
2269 */
2270 if (intel_fb_is_ccs_modifier(fb->modifier)) {
2271 ret = skl_check_ccs_aux_surface(plane_state);
2272 if (ret)
2273 return ret;
2274 }
2275
2276 if (intel_format_info_is_yuv_semiplanar(fb->format,
2277 fb->modifier)) {
2278 ret = skl_check_nv12_aux_surface(plane_state);
2279 if (ret)
2280 return ret;
2281 }
2282
2283 ret = skl_check_main_surface(plane_state);
2284 if (ret)
2285 return ret;
2286
2287 return 0;
2288 }
2289
skl_fb_scalable(const struct drm_framebuffer * fb)2290 static bool skl_fb_scalable(const struct drm_framebuffer *fb)
2291 {
2292 struct intel_display *display;
2293
2294 if (!fb)
2295 return false;
2296
2297 display = to_intel_display(fb->dev);
2298
2299 switch (fb->format->format) {
2300 case DRM_FORMAT_C8:
2301 return false;
2302 case DRM_FORMAT_XRGB16161616F:
2303 case DRM_FORMAT_ARGB16161616F:
2304 case DRM_FORMAT_XBGR16161616F:
2305 case DRM_FORMAT_ABGR16161616F:
2306 return DISPLAY_VER(display) >= 11;
2307 default:
2308 return true;
2309 }
2310 }
2311
check_protection(struct intel_plane_state * plane_state)2312 static void check_protection(struct intel_plane_state *plane_state)
2313 {
2314 struct intel_display *display = to_intel_display(plane_state);
2315 const struct drm_framebuffer *fb = plane_state->hw.fb;
2316 struct drm_gem_object *obj = intel_fb_bo(fb);
2317
2318 if (DISPLAY_VER(display) < 11)
2319 return;
2320
2321 plane_state->decrypt = intel_bo_key_check(obj) == 0;
2322 plane_state->force_black = intel_bo_is_protected(obj) &&
2323 !plane_state->decrypt;
2324 }
2325
2326 static void
make_damage_viewport_relative(struct intel_plane_state * plane_state)2327 make_damage_viewport_relative(struct intel_plane_state *plane_state)
2328 {
2329 const struct drm_framebuffer *fb = plane_state->hw.fb;
2330 const struct drm_rect *src = &plane_state->uapi.src;
2331 unsigned int rotation = plane_state->hw.rotation;
2332 struct drm_rect *damage = &plane_state->damage;
2333
2334 if (!drm_rect_visible(damage))
2335 return;
2336
2337 if (!fb || !plane_state->uapi.visible) {
2338 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0);
2339 return;
2340 }
2341
2342 if (drm_rotation_90_or_270(rotation)) {
2343 drm_rect_rotate(damage, fb->width, fb->height,
2344 DRM_MODE_ROTATE_270);
2345 drm_rect_translate(damage, -(src->y1 >> 16), -(src->x1 >> 16));
2346 } else {
2347 drm_rect_translate(damage, -(src->x1 >> 16), -(src->y1 >> 16));
2348 }
2349 }
2350
clip_damage(struct intel_plane_state * plane_state)2351 static void clip_damage(struct intel_plane_state *plane_state)
2352 {
2353 struct drm_rect *damage = &plane_state->damage;
2354 struct drm_rect src;
2355
2356 if (!drm_rect_visible(damage))
2357 return;
2358
2359 drm_rect_fp_to_int(&src, &plane_state->uapi.src);
2360 drm_rect_translate(damage, src.x1, src.y1);
2361 drm_rect_intersect(damage, &src);
2362 }
2363
skl_plane_check(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)2364 static int skl_plane_check(struct intel_crtc_state *crtc_state,
2365 struct intel_plane_state *plane_state)
2366 {
2367 struct intel_display *display = to_intel_display(plane_state);
2368 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2369 const struct drm_framebuffer *fb = plane_state->hw.fb;
2370 int min_scale = DRM_PLANE_NO_SCALING;
2371 int max_scale = DRM_PLANE_NO_SCALING;
2372 int ret;
2373
2374 ret = skl_plane_check_fb(crtc_state, plane_state);
2375 if (ret)
2376 return ret;
2377
2378 /* use scaler when colorkey is not required */
2379 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
2380 min_scale = 1;
2381 max_scale = skl_plane_max_scale(display, fb);
2382 }
2383
2384 ret = intel_plane_check_clipping(plane_state, crtc_state,
2385 min_scale, max_scale, true);
2386 if (ret)
2387 return ret;
2388
2389 make_damage_viewport_relative(plane_state);
2390
2391 ret = skl_check_plane_surface(plane_state);
2392 if (ret)
2393 return ret;
2394
2395 if (!plane_state->uapi.visible)
2396 return 0;
2397
2398 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2399 if (ret)
2400 return ret;
2401
2402 ret = intel_plane_check_src_coordinates(plane_state);
2403 if (ret)
2404 return ret;
2405
2406 clip_damage(plane_state);
2407
2408 ret = skl_plane_check_nv12_rotation(plane_state);
2409 if (ret)
2410 return ret;
2411
2412 check_protection(plane_state);
2413
2414 /* HW only has 8 bits pixel precision, disable plane if invisible */
2415 if (!(plane_state->hw.alpha >> 8)) {
2416 plane_state->uapi.visible = false;
2417 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0);
2418 }
2419
2420 plane_state->ctl = skl_plane_ctl(plane_state);
2421
2422 if (DISPLAY_VER(display) >= 10)
2423 plane_state->color_ctl = glk_plane_color_ctl(plane_state);
2424
2425 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2426 icl_is_hdr_plane(display, plane->id))
2427 /* Enable and use MPEG-2 chroma siting */
2428 plane_state->cus_ctl = PLANE_CUS_ENABLE |
2429 PLANE_CUS_HPHASE_0 |
2430 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2431 else
2432 plane_state->cus_ctl = 0;
2433
2434 return 0;
2435 }
2436
icl_link_nv12_planes(struct intel_plane_state * uv_plane_state,struct intel_plane_state * y_plane_state)2437 void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state,
2438 struct intel_plane_state *y_plane_state)
2439 {
2440 struct intel_display *display = to_intel_display(uv_plane_state);
2441 struct intel_plane *uv_plane = to_intel_plane(uv_plane_state->uapi.plane);
2442 struct intel_plane *y_plane = to_intel_plane(y_plane_state->uapi.plane);
2443
2444 drm_WARN_ON(display->drm, icl_is_nv12_y_plane(display, uv_plane->id));
2445 drm_WARN_ON(display->drm, !icl_is_nv12_y_plane(display, y_plane->id));
2446
2447 y_plane_state->ctl |= PLANE_CTL_YUV420_Y_PLANE;
2448
2449 if (icl_is_hdr_plane(display, uv_plane->id)) {
2450 switch (y_plane->id) {
2451 case PLANE_7:
2452 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_7_ICL;
2453 break;
2454 case PLANE_6:
2455 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_6_ICL;
2456 break;
2457 case PLANE_5:
2458 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_5_RKL;
2459 break;
2460 case PLANE_4:
2461 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_4_RKL;
2462 break;
2463 default:
2464 MISSING_CASE(y_plane->id);
2465 }
2466 }
2467 }
2468
skl_plane_fbc(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2469 static struct intel_fbc *skl_plane_fbc(struct intel_display *display,
2470 enum pipe pipe, enum plane_id plane_id)
2471 {
2472 enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
2473
2474 if (skl_plane_has_fbc(display, fbc_id, plane_id))
2475 return display->fbc.instances[fbc_id];
2476 else
2477 return NULL;
2478 }
2479
skl_plane_has_planar(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2480 static bool skl_plane_has_planar(struct intel_display *display,
2481 enum pipe pipe, enum plane_id plane_id)
2482 {
2483 /* Display WA #0870: skl, bxt */
2484 if (display->platform.skylake || display->platform.broxton)
2485 return false;
2486
2487 if (pipe == PIPE_C)
2488 return false;
2489
2490 return plane_id == PLANE_1 || plane_id == PLANE_2;
2491 }
2492
skl_get_plane_formats(struct intel_display * display,enum pipe pipe,enum plane_id plane_id,int * num_formats)2493 static const u32 *skl_get_plane_formats(struct intel_display *display,
2494 enum pipe pipe, enum plane_id plane_id,
2495 int *num_formats)
2496 {
2497 if (skl_plane_has_planar(display, pipe, plane_id)) {
2498 *num_formats = ARRAY_SIZE(skl_planar_formats);
2499 return skl_planar_formats;
2500 } else {
2501 *num_formats = ARRAY_SIZE(skl_plane_formats);
2502 return skl_plane_formats;
2503 }
2504 }
2505
glk_plane_has_planar(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2506 static bool glk_plane_has_planar(struct intel_display *display,
2507 enum pipe pipe, enum plane_id plane_id)
2508 {
2509 return plane_id == PLANE_1 || plane_id == PLANE_2;
2510 }
2511
glk_get_plane_formats(struct intel_display * display,enum pipe pipe,enum plane_id plane_id,int * num_formats)2512 static const u32 *glk_get_plane_formats(struct intel_display *display,
2513 enum pipe pipe, enum plane_id plane_id,
2514 int *num_formats)
2515 {
2516 if (glk_plane_has_planar(display, pipe, plane_id)) {
2517 *num_formats = ARRAY_SIZE(glk_planar_formats);
2518 return glk_planar_formats;
2519 } else {
2520 *num_formats = ARRAY_SIZE(skl_plane_formats);
2521 return skl_plane_formats;
2522 }
2523 }
2524
icl_get_plane_formats(struct intel_display * display,enum pipe pipe,enum plane_id plane_id,int * num_formats)2525 static const u32 *icl_get_plane_formats(struct intel_display *display,
2526 enum pipe pipe, enum plane_id plane_id,
2527 int *num_formats)
2528 {
2529 if (icl_is_hdr_plane(display, plane_id)) {
2530 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2531 return icl_hdr_plane_formats;
2532 } else if (icl_is_nv12_y_plane(display, plane_id)) {
2533 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2534 return icl_sdr_y_plane_formats;
2535 } else {
2536 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2537 return icl_sdr_uv_plane_formats;
2538 }
2539 }
2540
skl_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)2541 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2542 u32 format, u64 modifier)
2543 {
2544 struct intel_plane *plane = to_intel_plane(_plane);
2545
2546 if (!intel_fb_plane_supports_modifier(plane, modifier))
2547 return false;
2548
2549 switch (format) {
2550 case DRM_FORMAT_XRGB8888:
2551 case DRM_FORMAT_XBGR8888:
2552 case DRM_FORMAT_ARGB8888:
2553 case DRM_FORMAT_ABGR8888:
2554 if (intel_fb_is_ccs_modifier(modifier))
2555 return true;
2556 fallthrough;
2557 case DRM_FORMAT_RGB565:
2558 case DRM_FORMAT_XRGB2101010:
2559 case DRM_FORMAT_XBGR2101010:
2560 case DRM_FORMAT_ARGB2101010:
2561 case DRM_FORMAT_ABGR2101010:
2562 case DRM_FORMAT_YUYV:
2563 case DRM_FORMAT_YVYU:
2564 case DRM_FORMAT_UYVY:
2565 case DRM_FORMAT_VYUY:
2566 case DRM_FORMAT_NV12:
2567 case DRM_FORMAT_XYUV8888:
2568 case DRM_FORMAT_P010:
2569 case DRM_FORMAT_P012:
2570 case DRM_FORMAT_P016:
2571 case DRM_FORMAT_XVYU2101010:
2572 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2573 return true;
2574 fallthrough;
2575 case DRM_FORMAT_C8:
2576 case DRM_FORMAT_XBGR16161616F:
2577 case DRM_FORMAT_ABGR16161616F:
2578 case DRM_FORMAT_XRGB16161616F:
2579 case DRM_FORMAT_ARGB16161616F:
2580 case DRM_FORMAT_Y210:
2581 case DRM_FORMAT_Y212:
2582 case DRM_FORMAT_Y216:
2583 case DRM_FORMAT_XVYU12_16161616:
2584 case DRM_FORMAT_XVYU16161616:
2585 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2586 modifier == I915_FORMAT_MOD_X_TILED ||
2587 modifier == I915_FORMAT_MOD_Y_TILED)
2588 return true;
2589 fallthrough;
2590 default:
2591 return false;
2592 }
2593 }
2594
icl_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)2595 static bool icl_plane_format_mod_supported(struct drm_plane *_plane,
2596 u32 format, u64 modifier)
2597 {
2598 struct intel_plane *plane = to_intel_plane(_plane);
2599
2600 if (!intel_fb_plane_supports_modifier(plane, modifier))
2601 return false;
2602
2603 switch (format) {
2604 case DRM_FORMAT_XRGB8888:
2605 case DRM_FORMAT_XBGR8888:
2606 case DRM_FORMAT_ARGB8888:
2607 case DRM_FORMAT_ABGR8888:
2608 case DRM_FORMAT_XRGB2101010:
2609 case DRM_FORMAT_XBGR2101010:
2610 case DRM_FORMAT_ARGB2101010:
2611 case DRM_FORMAT_ABGR2101010:
2612 if (intel_fb_is_ccs_modifier(modifier))
2613 return true;
2614 fallthrough;
2615 case DRM_FORMAT_RGB565:
2616 case DRM_FORMAT_YUYV:
2617 case DRM_FORMAT_YVYU:
2618 case DRM_FORMAT_UYVY:
2619 case DRM_FORMAT_VYUY:
2620 case DRM_FORMAT_NV12:
2621 case DRM_FORMAT_XYUV8888:
2622 case DRM_FORMAT_P010:
2623 case DRM_FORMAT_P012:
2624 case DRM_FORMAT_P016:
2625 case DRM_FORMAT_XVYU2101010:
2626 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2627 return true;
2628 fallthrough;
2629 case DRM_FORMAT_C8:
2630 case DRM_FORMAT_XBGR16161616F:
2631 case DRM_FORMAT_ABGR16161616F:
2632 case DRM_FORMAT_XRGB16161616F:
2633 case DRM_FORMAT_ARGB16161616F:
2634 case DRM_FORMAT_Y210:
2635 case DRM_FORMAT_Y212:
2636 case DRM_FORMAT_Y216:
2637 case DRM_FORMAT_XVYU12_16161616:
2638 case DRM_FORMAT_XVYU16161616:
2639 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2640 modifier == I915_FORMAT_MOD_X_TILED ||
2641 modifier == I915_FORMAT_MOD_Y_TILED)
2642 return true;
2643 fallthrough;
2644 default:
2645 return false;
2646 }
2647 }
2648
tgl_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)2649 static bool tgl_plane_format_mod_supported(struct drm_plane *_plane,
2650 u32 format, u64 modifier)
2651 {
2652 struct intel_plane *plane = to_intel_plane(_plane);
2653
2654 if (!intel_fb_plane_supports_modifier(plane, modifier))
2655 return false;
2656
2657 switch (format) {
2658 case DRM_FORMAT_XRGB8888:
2659 case DRM_FORMAT_XBGR8888:
2660 case DRM_FORMAT_ARGB8888:
2661 case DRM_FORMAT_ABGR8888:
2662 case DRM_FORMAT_XRGB2101010:
2663 case DRM_FORMAT_XBGR2101010:
2664 case DRM_FORMAT_ARGB2101010:
2665 case DRM_FORMAT_ABGR2101010:
2666 case DRM_FORMAT_XBGR16161616F:
2667 case DRM_FORMAT_ABGR16161616F:
2668 case DRM_FORMAT_XRGB16161616F:
2669 case DRM_FORMAT_ARGB16161616F:
2670 if (intel_fb_is_ccs_modifier(modifier))
2671 return true;
2672 fallthrough;
2673 case DRM_FORMAT_YUYV:
2674 case DRM_FORMAT_YVYU:
2675 case DRM_FORMAT_UYVY:
2676 case DRM_FORMAT_VYUY:
2677 case DRM_FORMAT_NV12:
2678 case DRM_FORMAT_XYUV8888:
2679 case DRM_FORMAT_P010:
2680 case DRM_FORMAT_P012:
2681 case DRM_FORMAT_P016:
2682 if (intel_fb_is_mc_ccs_modifier(modifier))
2683 return true;
2684 fallthrough;
2685 case DRM_FORMAT_RGB565:
2686 case DRM_FORMAT_XVYU2101010:
2687 case DRM_FORMAT_C8:
2688 case DRM_FORMAT_Y210:
2689 case DRM_FORMAT_Y212:
2690 case DRM_FORMAT_Y216:
2691 case DRM_FORMAT_XVYU12_16161616:
2692 case DRM_FORMAT_XVYU16161616:
2693 if (!intel_fb_is_ccs_modifier(modifier))
2694 return true;
2695 fallthrough;
2696 default:
2697 return false;
2698 }
2699 }
2700
2701 static const struct drm_plane_funcs skl_plane_funcs = {
2702 .update_plane = drm_atomic_helper_update_plane,
2703 .disable_plane = drm_atomic_helper_disable_plane,
2704 .destroy = intel_plane_destroy,
2705 .atomic_duplicate_state = intel_plane_duplicate_state,
2706 .atomic_destroy_state = intel_plane_destroy_state,
2707 .format_mod_supported = skl_plane_format_mod_supported,
2708 .format_mod_supported_async = intel_plane_format_mod_supported_async,
2709 };
2710
2711 static const struct drm_plane_funcs icl_plane_funcs = {
2712 .update_plane = drm_atomic_helper_update_plane,
2713 .disable_plane = drm_atomic_helper_disable_plane,
2714 .destroy = intel_plane_destroy,
2715 .atomic_duplicate_state = intel_plane_duplicate_state,
2716 .atomic_destroy_state = intel_plane_destroy_state,
2717 .format_mod_supported = icl_plane_format_mod_supported,
2718 .format_mod_supported_async = intel_plane_format_mod_supported_async,
2719 };
2720
2721 static const struct drm_plane_funcs tgl_plane_funcs = {
2722 .update_plane = drm_atomic_helper_update_plane,
2723 .disable_plane = drm_atomic_helper_disable_plane,
2724 .destroy = intel_plane_destroy,
2725 .atomic_duplicate_state = intel_plane_duplicate_state,
2726 .atomic_destroy_state = intel_plane_destroy_state,
2727 .format_mod_supported = tgl_plane_format_mod_supported,
2728 .format_mod_supported_async = intel_plane_format_mod_supported_async,
2729 };
2730
2731 static void
skl_plane_enable_flip_done(struct intel_plane * plane)2732 skl_plane_enable_flip_done(struct intel_plane *plane)
2733 {
2734 struct intel_display *display = to_intel_display(plane);
2735 enum pipe pipe = plane->pipe;
2736
2737 spin_lock_irq(&display->irq.lock);
2738 bdw_enable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2739 spin_unlock_irq(&display->irq.lock);
2740 }
2741
2742 static void
skl_plane_disable_flip_done(struct intel_plane * plane)2743 skl_plane_disable_flip_done(struct intel_plane *plane)
2744 {
2745 struct intel_display *display = to_intel_display(plane);
2746 enum pipe pipe = plane->pipe;
2747
2748 spin_lock_irq(&display->irq.lock);
2749 bdw_disable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2750 spin_unlock_irq(&display->irq.lock);
2751 }
2752
skl_plane_has_rc_ccs(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2753 static bool skl_plane_has_rc_ccs(struct intel_display *display,
2754 enum pipe pipe, enum plane_id plane_id)
2755 {
2756 if (pipe == PIPE_C)
2757 return false;
2758
2759 return plane_id == PLANE_1 || plane_id == PLANE_2;
2760 }
2761
skl_plane_caps(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2762 static u8 skl_plane_caps(struct intel_display *display,
2763 enum pipe pipe, enum plane_id plane_id)
2764 {
2765 u8 caps = INTEL_PLANE_CAP_TILING_X |
2766 INTEL_PLANE_CAP_TILING_Y |
2767 INTEL_PLANE_CAP_TILING_Yf;
2768
2769 if (skl_plane_has_rc_ccs(display, pipe, plane_id))
2770 caps |= INTEL_PLANE_CAP_CCS_RC;
2771
2772 return caps;
2773 }
2774
glk_plane_has_rc_ccs(struct intel_display * display,enum pipe pipe)2775 static bool glk_plane_has_rc_ccs(struct intel_display *display,
2776 enum pipe pipe)
2777 {
2778 return pipe != PIPE_C;
2779 }
2780
glk_plane_caps(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2781 static u8 glk_plane_caps(struct intel_display *display,
2782 enum pipe pipe, enum plane_id plane_id)
2783 {
2784 u8 caps = INTEL_PLANE_CAP_TILING_X |
2785 INTEL_PLANE_CAP_TILING_Y |
2786 INTEL_PLANE_CAP_TILING_Yf;
2787
2788 if (glk_plane_has_rc_ccs(display, pipe))
2789 caps |= INTEL_PLANE_CAP_CCS_RC;
2790
2791 return caps;
2792 }
2793
icl_plane_caps(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2794 static u8 icl_plane_caps(struct intel_display *display,
2795 enum pipe pipe, enum plane_id plane_id)
2796 {
2797 return INTEL_PLANE_CAP_TILING_X |
2798 INTEL_PLANE_CAP_TILING_Y |
2799 INTEL_PLANE_CAP_TILING_Yf |
2800 INTEL_PLANE_CAP_CCS_RC;
2801 }
2802
tgl_plane_has_mc_ccs(struct intel_display * display,enum plane_id plane_id)2803 static bool tgl_plane_has_mc_ccs(struct intel_display *display,
2804 enum plane_id plane_id)
2805 {
2806 /* Wa_14010477008 */
2807 if (intel_display_wa(display, INTEL_DISPLAY_WA_14010477008))
2808 return false;
2809
2810 return plane_id < PLANE_6;
2811 }
2812
tgl_plane_caps(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2813 static u8 tgl_plane_caps(struct intel_display *display,
2814 enum pipe pipe, enum plane_id plane_id)
2815 {
2816 u8 caps = INTEL_PLANE_CAP_TILING_X |
2817 INTEL_PLANE_CAP_CCS_RC |
2818 INTEL_PLANE_CAP_CCS_RC_CC;
2819
2820 if (HAS_4TILE(display))
2821 caps |= INTEL_PLANE_CAP_TILING_4;
2822 else
2823 caps |= INTEL_PLANE_CAP_TILING_Y;
2824
2825 if (tgl_plane_has_mc_ccs(display, plane_id))
2826 caps |= INTEL_PLANE_CAP_CCS_MC;
2827
2828 if (DISPLAY_VER(display) >= 14 && display->platform.dgfx)
2829 caps |= INTEL_PLANE_CAP_NEED64K_PHYS;
2830
2831 return caps;
2832 }
2833
skl_disable_tiling(struct intel_plane * plane)2834 static void skl_disable_tiling(struct intel_plane *plane)
2835 {
2836 struct intel_plane_state *state = to_intel_plane_state(plane->base.state);
2837 struct intel_display *display = to_intel_display(plane);
2838 const struct drm_framebuffer *fb = state->hw.fb;
2839 u32 plane_ctl;
2840
2841 plane_ctl = intel_de_read(display, PLANE_CTL(plane->pipe, plane->id));
2842
2843 if (intel_fb_uses_dpt(fb)) {
2844 /* if DPT is enabled, keep tiling, but disable compression */
2845 plane_ctl &= ~PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
2846 } else {
2847 /* if DPT is not supported, disable tiling, and update stride */
2848 u32 stride = state->view.color_plane[0].scanout_stride / 64;
2849
2850 plane_ctl &= ~PLANE_CTL_TILED_MASK;
2851 intel_de_write_fw(display, PLANE_STRIDE(plane->pipe, plane->id),
2852 PLANE_STRIDE_(stride));
2853 }
2854 intel_de_write_fw(display, PLANE_CTL(plane->pipe, plane->id), plane_ctl);
2855
2856 intel_de_write_fw(display, PLANE_SURF(plane->pipe, plane->id),
2857 state->surf);
2858 }
2859
2860 struct intel_plane *
skl_universal_plane_create(struct intel_display * display,enum pipe pipe,enum plane_id plane_id)2861 skl_universal_plane_create(struct intel_display *display,
2862 enum pipe pipe, enum plane_id plane_id)
2863 {
2864 const struct drm_plane_funcs *plane_funcs;
2865 struct intel_plane *plane;
2866 enum drm_plane_type plane_type;
2867 unsigned int supported_rotations;
2868 unsigned int supported_csc;
2869 const u64 *modifiers;
2870 const u32 *formats;
2871 int num_formats;
2872 int ret;
2873 u8 caps;
2874
2875 plane = intel_plane_alloc();
2876 if (IS_ERR(plane))
2877 return plane;
2878
2879 plane->pipe = pipe;
2880 plane->id = plane_id;
2881 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2882
2883 intel_fbc_add_plane(skl_plane_fbc(display, pipe, plane_id), plane);
2884
2885 if (DISPLAY_VER(display) >= 30) {
2886 plane->min_width = adl_plane_min_width;
2887 plane->max_width = xe3_plane_max_width;
2888 plane->max_height = icl_plane_max_height;
2889 plane->min_cdclk = icl_plane_min_cdclk;
2890 } else if (DISPLAY_VER(display) >= 11) {
2891 if (DISPLAY_VER(display) >= 14 || display->platform.alderlake_p)
2892 plane->min_width = adl_plane_min_width;
2893 else
2894 plane->min_width = icl_plane_min_width;
2895 if (icl_is_hdr_plane(display, plane_id))
2896 plane->max_width = icl_hdr_plane_max_width;
2897 else
2898 plane->max_width = icl_sdr_plane_max_width;
2899 plane->max_height = icl_plane_max_height;
2900 plane->min_cdclk = icl_plane_min_cdclk;
2901 } else if (DISPLAY_VER(display) >= 10) {
2902 plane->max_width = glk_plane_max_width;
2903 plane->max_height = skl_plane_max_height;
2904 plane->min_cdclk = glk_plane_min_cdclk;
2905 } else {
2906 plane->max_width = skl_plane_max_width;
2907 plane->max_height = skl_plane_max_height;
2908 plane->min_cdclk = skl_plane_min_cdclk;
2909 }
2910 plane->disable_tiling = skl_disable_tiling;
2911
2912 plane->surf_offset = skl_plane_surf_offset;
2913
2914 if (DISPLAY_VER(display) >= 13)
2915 plane->max_stride = adl_plane_max_stride;
2916 else
2917 plane->max_stride = skl_plane_max_stride;
2918
2919 if (DISPLAY_VER(display) >= 12)
2920 plane->min_alignment = tgl_plane_min_alignment;
2921 else
2922 plane->min_alignment = skl_plane_min_alignment;
2923
2924 if (intel_scanout_needs_vtd_wa(display))
2925 plane->vtd_guard = DISPLAY_VER(display) >= 10 ? 168 : 136;
2926
2927 if (DISPLAY_VER(display) >= 11) {
2928 plane->update_noarm = icl_plane_update_noarm;
2929 plane->update_arm = icl_plane_update_arm;
2930 plane->disable_arm = icl_plane_disable_arm;
2931 } else {
2932 plane->update_noarm = skl_plane_update_noarm;
2933 plane->update_arm = skl_plane_update_arm;
2934 plane->disable_arm = skl_plane_disable_arm;
2935 }
2936 plane->capture_error = skl_plane_capture_error;
2937 plane->get_hw_state = skl_plane_get_hw_state;
2938 plane->check_plane = skl_plane_check;
2939
2940 if (HAS_ASYNC_FLIPS(display) && plane_id == PLANE_1) {
2941 plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(display, 9, 10);
2942 plane->async_flip = skl_plane_async_flip;
2943 plane->enable_flip_done = skl_plane_enable_flip_done;
2944 plane->disable_flip_done = skl_plane_disable_flip_done;
2945
2946 if (DISPLAY_VER(display) >= 12)
2947 plane->can_async_flip = tgl_plane_can_async_flip;
2948 else if (DISPLAY_VER(display) == 11)
2949 plane->can_async_flip = icl_plane_can_async_flip;
2950 else
2951 plane->can_async_flip = skl_plane_can_async_flip;
2952 }
2953
2954 if (DISPLAY_VER(display) >= 11)
2955 formats = icl_get_plane_formats(display, pipe,
2956 plane_id, &num_formats);
2957 else if (DISPLAY_VER(display) >= 10)
2958 formats = glk_get_plane_formats(display, pipe,
2959 plane_id, &num_formats);
2960 else
2961 formats = skl_get_plane_formats(display, pipe,
2962 plane_id, &num_formats);
2963
2964 if (DISPLAY_VER(display) >= 12)
2965 plane_funcs = &tgl_plane_funcs;
2966 else if (DISPLAY_VER(display) == 11)
2967 plane_funcs = &icl_plane_funcs;
2968 else
2969 plane_funcs = &skl_plane_funcs;
2970
2971 if (plane_id == PLANE_1)
2972 plane_type = DRM_PLANE_TYPE_PRIMARY;
2973 else
2974 plane_type = DRM_PLANE_TYPE_OVERLAY;
2975
2976 if (DISPLAY_VER(display) >= 12)
2977 caps = tgl_plane_caps(display, pipe, plane_id);
2978 else if (DISPLAY_VER(display) == 11)
2979 caps = icl_plane_caps(display, pipe, plane_id);
2980 else if (DISPLAY_VER(display) == 10)
2981 caps = glk_plane_caps(display, pipe, plane_id);
2982 else
2983 caps = skl_plane_caps(display, pipe, plane_id);
2984
2985 modifiers = intel_fb_plane_get_modifiers(display, caps);
2986
2987 ret = drm_universal_plane_init(display->drm, &plane->base,
2988 0, plane_funcs,
2989 formats, num_formats, modifiers,
2990 plane_type,
2991 "plane %d%c", plane_id + 1,
2992 pipe_name(pipe));
2993
2994 kfree(modifiers);
2995
2996 if (ret)
2997 goto fail;
2998
2999 if (DISPLAY_VER(display) >= 13)
3000 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
3001 else
3002 supported_rotations =
3003 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
3004 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
3005
3006 if (DISPLAY_VER(display) >= 11)
3007 supported_rotations |= DRM_MODE_REFLECT_X;
3008
3009 drm_plane_create_rotation_property(&plane->base,
3010 DRM_MODE_ROTATE_0,
3011 supported_rotations);
3012
3013 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
3014
3015 if (DISPLAY_VER(display) >= 10)
3016 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
3017
3018 drm_plane_create_color_properties(&plane->base,
3019 supported_csc,
3020 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3021 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3022 DRM_COLOR_YCBCR_BT709,
3023 DRM_COLOR_YCBCR_LIMITED_RANGE);
3024
3025 if (DISPLAY_VER(display) >= 12)
3026 intel_color_pipeline_plane_init(&plane->base, pipe);
3027
3028 drm_plane_create_alpha_property(&plane->base);
3029 drm_plane_create_blend_mode_property(&plane->base,
3030 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
3031 BIT(DRM_MODE_BLEND_PREMULTI) |
3032 BIT(DRM_MODE_BLEND_COVERAGE));
3033
3034 drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
3035
3036 if (DISPLAY_VER(display) >= 12)
3037 drm_plane_enable_fb_damage_clips(&plane->base);
3038
3039 if (DISPLAY_VER(display) >= 11)
3040 drm_plane_create_scaling_filter_property(&plane->base,
3041 BIT(DRM_SCALING_FILTER_DEFAULT) |
3042 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
3043
3044 intel_plane_helper_add(plane);
3045
3046 return plane;
3047
3048 fail:
3049 intel_plane_free(plane);
3050
3051 return ERR_PTR(ret);
3052 }
3053
3054 void
skl_get_initial_plane_config(struct intel_crtc * crtc,struct intel_initial_plane_config * plane_config)3055 skl_get_initial_plane_config(struct intel_crtc *crtc,
3056 struct intel_initial_plane_config *plane_config)
3057 {
3058 struct intel_display *display = to_intel_display(crtc);
3059 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
3060 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
3061 enum plane_id plane_id = plane->id;
3062 enum pipe pipe;
3063 u32 val, base, offset, stride_mult, tiling, alpha;
3064 int fourcc, pixel_format;
3065 unsigned int aligned_height;
3066 struct drm_framebuffer *fb;
3067 struct intel_framebuffer *intel_fb;
3068 static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
3069
3070 if (!plane->get_hw_state(plane, &pipe))
3071 return;
3072
3073 drm_WARN_ON(display->drm, pipe != crtc->pipe);
3074
3075 if (crtc_state->joiner_pipes) {
3076 drm_dbg_kms(display->drm,
3077 "[CRTC:%d:%s] Unsupported joiner configuration for initial FB\n",
3078 crtc->base.base.id, crtc->base.name);
3079 return;
3080 }
3081
3082 intel_fb = intel_framebuffer_alloc();
3083 if (!intel_fb) {
3084 drm_dbg_kms(display->drm, "failed to alloc fb\n");
3085 return;
3086 }
3087
3088 fb = &intel_fb->base;
3089
3090 fb->dev = display->drm;
3091
3092 val = intel_de_read(display, PLANE_CTL(pipe, plane_id));
3093
3094 if (DISPLAY_VER(display) >= 11)
3095 pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL;
3096 else
3097 pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL;
3098
3099 if (DISPLAY_VER(display) >= 10) {
3100 u32 color_ctl;
3101
3102 color_ctl = intel_de_read(display, PLANE_COLOR_CTL(pipe, plane_id));
3103 alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl);
3104 } else {
3105 alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val);
3106 }
3107
3108 fourcc = skl_format_to_fourcc(pixel_format,
3109 val & PLANE_CTL_ORDER_RGBX, alpha);
3110
3111 tiling = val & PLANE_CTL_TILED_MASK;
3112 switch (tiling) {
3113 case PLANE_CTL_TILED_LINEAR:
3114 fb->modifier = DRM_FORMAT_MOD_LINEAR;
3115 break;
3116 case PLANE_CTL_TILED_X:
3117 fb->modifier = I915_FORMAT_MOD_X_TILED;
3118 break;
3119 case PLANE_CTL_TILED_Y:
3120 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
3121 if (DISPLAY_VER(display) >= 14)
3122 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS;
3123 else if (DISPLAY_VER(display) >= 12)
3124 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
3125 else
3126 fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
3127 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
3128 if (DISPLAY_VER(display) >= 14)
3129 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS;
3130 else
3131 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
3132 else
3133 fb->modifier = I915_FORMAT_MOD_Y_TILED;
3134 break;
3135 case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
3136 if (HAS_4TILE(display)) {
3137 u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
3138 PLANE_CTL_CLEAR_COLOR_DISABLE;
3139
3140 if ((val & rc_mask) == rc_mask)
3141 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
3142 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
3143 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
3144 else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
3145 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
3146 else
3147 fb->modifier = I915_FORMAT_MOD_4_TILED;
3148 } else {
3149 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
3150 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
3151 else
3152 fb->modifier = I915_FORMAT_MOD_Yf_TILED;
3153 }
3154 break;
3155 default:
3156 MISSING_CASE(tiling);
3157 goto error;
3158 }
3159
3160 fb->format = drm_get_format_info(display->drm, fourcc, fb->modifier);
3161
3162 /*
3163 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
3164 * while i915 HW rotation is clockwise, that's why this swapping.
3165 */
3166 switch (val & PLANE_CTL_ROTATE_MASK) {
3167 case PLANE_CTL_ROTATE_0:
3168 plane_config->rotation = DRM_MODE_ROTATE_0;
3169 break;
3170 case PLANE_CTL_ROTATE_90:
3171 plane_config->rotation = DRM_MODE_ROTATE_270;
3172 break;
3173 case PLANE_CTL_ROTATE_180:
3174 plane_config->rotation = DRM_MODE_ROTATE_180;
3175 break;
3176 case PLANE_CTL_ROTATE_270:
3177 plane_config->rotation = DRM_MODE_ROTATE_90;
3178 break;
3179 }
3180
3181 if (DISPLAY_VER(display) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
3182 plane_config->rotation |= DRM_MODE_REFLECT_X;
3183
3184 /* 90/270 degree rotation would require extra work */
3185 if (drm_rotation_90_or_270(plane_config->rotation))
3186 goto error;
3187
3188 base = intel_de_read(display, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK;
3189 plane_config->base = base;
3190
3191 offset = intel_de_read(display, PLANE_OFFSET(pipe, plane_id));
3192 drm_WARN_ON(display->drm, offset != 0);
3193
3194 val = intel_de_read(display, PLANE_SIZE(pipe, plane_id));
3195 fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1;
3196 fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1;
3197
3198 val = intel_de_read(display, PLANE_STRIDE(pipe, plane_id));
3199 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
3200
3201 fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult;
3202
3203 aligned_height = intel_fb_align_height(fb, 0, fb->height);
3204
3205 plane_config->size = fb->pitches[0] * aligned_height;
3206
3207 drm_dbg_kms(display->drm,
3208 "[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
3209 crtc->base.base.id, crtc->base.name,
3210 plane->base.base.id, plane->base.name,
3211 fb->width, fb->height, fb->format->cpp[0] * 8,
3212 base, fb->pitches[0], plane_config->size);
3213
3214 plane_config->fb = &intel_fb->base;
3215 return;
3216
3217 error:
3218 kfree(intel_fb);
3219 }
3220
skl_fixup_initial_plane_config(struct intel_crtc * crtc,const struct intel_initial_plane_config * plane_config)3221 bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
3222 const struct intel_initial_plane_config *plane_config)
3223 {
3224 struct intel_display *display = to_intel_display(crtc);
3225 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
3226 const struct intel_plane_state *plane_state =
3227 to_intel_plane_state(plane->base.state);
3228 enum plane_id plane_id = plane->id;
3229 enum pipe pipe = crtc->pipe;
3230
3231 if (!plane_state->uapi.visible)
3232 return false;
3233
3234 /*
3235 * We may have moved the surface to a different
3236 * part of ggtt, make the plane aware of that.
3237 */
3238 if (plane_config->base == plane_state->surf)
3239 return false;
3240
3241 intel_de_write(display, PLANE_SURF(pipe, plane_id), plane_state->surf);
3242
3243 return true;
3244 }
3245